remove SkThread, using std::thread instead

Change-Id: I871dd5eea4496e87c206b46d9eae81cb521b11ce
Reviewed-on: https://skia-review.googlesource.com/65103
Reviewed-by: Hal Canary <halcanary@google.com>
Commit-Queue: Mike Klein <mtklein@chromium.org>
This commit is contained in:
Mike Klein 2017-10-30 11:57:15 -04:00 committed by Skia Commit-Bot
parent cc309eb9b1
commit 03141d25cf
14 changed files with 65 additions and 409 deletions

View File

@ -798,8 +798,6 @@ component("skia") {
} else {
sources += [ "src/ports/SkFontMgr_win_dw_factory.cpp" ]
}
sources -=
[ get_path_info("src/utils/SkThreadUtils_pthread.cpp", "abspath") ]
libs += [
"FontSub.lib",
"Ole32.lib",

View File

@ -45,13 +45,13 @@
#include "SkString.h"
#include "SkSurface.h"
#include "SkTaskGroup.h"
#include "SkThreadUtils.h"
#include "SkTraceEvent.h"
#include "Stats.h"
#include "ThermalManager.h"
#include "ios_utils.h"
#include <stdlib.h>
#include <thread>
extern bool gSkForceRasterPipelineBlitter;
@ -1109,21 +1109,18 @@ private:
// Some runs (mostly, Valgrind) are so slow that the bot framework thinks we've hung.
// This prints something every once in a while so that it knows we're still working.
static void start_keepalive() {
struct Loop {
static void forever(void*) {
for (;;) {
static const int kSec = 1200;
#if defined(SK_BUILD_FOR_WIN)
Sleep(kSec * 1000);
#else
sleep(kSec);
#endif
SkDebugf("\nBenchmarks still running...\n");
}
static std::thread* intentionallyLeaked = new std::thread([]{
for (;;) {
static const int kSec = 1200;
#if defined(SK_BUILD_FOR_WIN)
Sleep(kSec * 1000);
#else
sleep(kSec);
#endif
SkDebugf("\nBenchmarks still running...\n");
}
};
static SkThread* intentionallyLeaked = new SkThread(Loop::forever);
intentionallyLeaked->start();
});
(void)intentionallyLeaked;
}
int main(int argc, char** argv) {

View File

@ -38,7 +38,6 @@
#include "SkSpinlock.h"
#include "SkTHash.h"
#include "SkTaskGroup.h"
#include "SkThreadUtils.h"
#include "Test.h"
#include "Timer.h"
#include "ios_utils.h"

View File

@ -62,11 +62,8 @@ skia_utils_sources = [
"$_src/utils/SkShadowTessellator.h",
"$_src/utils/SkShadowUtils.cpp",
"$_src/utils/SkTextBox.cpp",
"$_src/utils/SkThreadUtils.h",
"$_src/utils/SkThreadUtils_pthread.cpp",
"$_src/utils/SkThreadUtils_pthread.h",
"$_src/utils/SkThreadUtils_win.cpp",
"$_src/utils/SkThreadUtils_win.h",
"$_src/utils/SkWhitelistTypefaces.cpp",
#mac

View File

@ -225,7 +225,6 @@ BASE_SRCS_ALL = struct(
"src/ports/**/*",
"src/utils/android/**/*",
"src/utils/mac/**/*",
"src/utils/SkThreadUtils_win.cpp", # Windows-only. Move to ports?
"src/utils/win/**/*",
"src/views/sdl/*",
"src/views/win/*",

View File

@ -11,8 +11,8 @@
#include "SkSemaphore.h"
#include "SkSpinlock.h"
#include "SkTArray.h"
#include "SkThreadUtils.h"
#include <deque>
#include <thread>
#if defined(SK_BUILD_FOR_WIN32)
#include <windows.h>
@ -65,8 +65,7 @@ class SkThreadPool final : public SkExecutor {
public:
explicit SkThreadPool(int threads) {
for (int i = 0; i < threads; i++) {
fThreads.emplace_back(new SkThread(&Loop, this));
fThreads.back()->start();
fThreads.emplace_back(&Loop, this);
}
}
@ -77,7 +76,7 @@ public:
}
// Wait for each thread to shut down.
for (int i = 0; i < fThreads.count(); i++) {
fThreads[i]->join();
fThreads[i].join();
}
}
@ -126,10 +125,10 @@ private:
// Both SkMutex and SkSpinlock can work here.
using Lock = SkMutex;
SkTArray<std::unique_ptr<SkThread>> fThreads;
WorkList fWork;
Lock fWorkLock;
SkSemaphore fWorkAvailable;
SkTArray<std::thread> fThreads;
WorkList fWork;
Lock fWorkLock;
SkSemaphore fWorkAvailable;
};
std::unique_ptr<SkExecutor> SkExecutor::MakeFIFOThreadPool(int threads) {

View File

@ -1,39 +0,0 @@
/*
* 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 = nullptr);
/**
* 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();
private:
void* fData;
};
#endif

View File

@ -1,117 +1,11 @@
/*
* Copyright 2012 Google Inc.
* Copyright 2017 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>
PThreadEvent::PThreadEvent() : fConditionFlag(false) {
pthread_cond_init(&fCondition, nullptr);
pthread_mutex_init(&fConditionMutex, nullptr);
}
PThreadEvent::~PThreadEvent() {
pthread_mutex_destroy(&fConditionMutex);
pthread_cond_destroy(&fCondition);
}
void PThreadEvent::trigger() {
pthread_mutex_lock(&fConditionMutex);
fConditionFlag = true;
pthread_cond_signal(&fCondition);
pthread_mutex_unlock(&fConditionMutex);
}
void PThreadEvent::wait() {
pthread_mutex_lock(&fConditionMutex);
while (!fConditionFlag) {
pthread_cond_wait(&fCondition, &fConditionMutex);
}
pthread_mutex_unlock(&fConditionMutex);
}
bool PThreadEvent::isTriggered() {
bool currentFlag;
pthread_mutex_lock(&fConditionMutex);
currentFlag = fConditionFlag;
pthread_mutex_unlock(&fConditionMutex);
return currentFlag;
}
SkThread_PThreadData::SkThread_PThreadData(SkThread::entryPointProc entryPoint, void* data)
: fPThread()
, fValidPThread(false)
, fParam(data)
, fEntryPoint(entryPoint)
{
pthread_attr_init(&fAttr);
pthread_attr_setdetachstate(&fAttr, PTHREAD_CREATE_JOINABLE);
}
SkThread_PThreadData::~SkThread_PThreadData() {
pthread_attr_destroy(&fAttr);
}
static void* thread_start(void* arg) {
SkThread_PThreadData* pthreadData = static_cast<SkThread_PThreadData*>(arg);
// Wait for start signal
pthreadData->fStarted.wait();
// Call entry point only if thread was not canceled before starting.
if (!pthreadData->fCanceled.isTriggered()) {
pthreadData->fEntryPoint(pthreadData->fParam);
}
return nullptr;
}
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 != nullptr) {
SkThread_PThreadData* pthreadData = static_cast<SkThread_PThreadData*>(fData);
// If created thread but start was never called, kill the thread.
if (pthreadData->fValidPThread && !pthreadData->fStarted.isTriggered()) {
pthreadData->fCanceled.trigger();
if (this->start()) {
this->join();
}
}
delete pthreadData;
}
}
bool SkThread::start() {
SkThread_PThreadData* pthreadData = static_cast<SkThread_PThreadData*>(fData);
if (!pthreadData->fValidPThread) {
return false;
}
if (pthreadData->fStarted.isTriggered()) {
return false;
}
pthreadData->fStarted.trigger();
return true;
}
void SkThread::join() {
SkThread_PThreadData* pthreadData = static_cast<SkThread_PThreadData*>(fData);
if (!pthreadData->fValidPThread || !pthreadData->fStarted.isTriggered()) {
return;
}
pthread_join(pthreadData->fPThread, nullptr);
}
// Nothing to see here.
//
// We just need to keep this file around until we do the song and dance
// to stop explicitly removing it from Chromium's GN build.

View File

@ -1,43 +0,0 @@
/*
* 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 PThreadEvent : SkNoncopyable {
public:
PThreadEvent();
~PThreadEvent();
void trigger();
void wait();
bool isTriggered();
private:
pthread_cond_t fCondition;
pthread_mutex_t fConditionMutex;
bool fConditionFlag;
};
class SkThread_PThreadData : SkNoncopyable {
public:
SkThread_PThreadData(SkThread::entryPointProc entryPoint, void* data);
~SkThread_PThreadData();
pthread_t fPThread;
bool fValidPThread;
PThreadEvent fStarted;
PThreadEvent fCanceled;
pthread_attr_t fAttr;
void* fParam;
SkThread::entryPointProc fEntryPoint;
};
#endif

View File

@ -1,101 +1,11 @@
/*
* Copyright 2012 Google Inc.
* Copyright 2017 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"
#if defined(SK_BUILD_FOR_WIN32)
#include "SkThreadUtils.h"
#include "SkThreadUtils_win.h"
SkThread_WinData::SkThread_WinData(SkThread::entryPointProc entryPoint, void* data)
: fHandle(nullptr)
, fParam(data)
, fThreadId(0)
, fEntryPoint(entryPoint)
, fStarted(false)
{
fCancelEvent = CreateEvent(
nullptr, // default security attributes
false, //auto reset
false, //not signaled
nullptr); //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 (nullptr == winData->fCancelEvent) {
return;
}
winData->fHandle = CreateThread(
nullptr, // default security attributes
0, // use default stack size
thread_start, // thread function name (proxy)
winData, // argument to thread function (proxy args)
CREATE_SUSPENDED, // we used to set processor affinity, which needed this
&winData->fThreadId); // returns the thread identifier
}
SkThread::~SkThread() {
if (fData != nullptr) {
SkThread_WinData* winData = static_cast<SkThread_WinData*>(fData);
// If created thread but start was never called, kill the thread.
if (winData->fHandle != nullptr && !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 (nullptr == 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 (nullptr == winData->fHandle || !winData->fStarted) {
return;
}
WaitForSingleObject(winData->fHandle, INFINITE);
}
#endif//defined(SK_BUILD_FOR_WIN32)
// Nothing to see here.
//
// We just need to keep this file around until we do the song and dance
// to stop explicitly removing it from Chromium's GN build.

View File

@ -1,27 +0,0 @@
/*
* 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 "SkLeanWindows.h"
#include "SkThreadUtils.h"
class SkThread_WinData : SkNoncopyable {
public:
SkThread_WinData(SkThread::entryPointProc entryPoint, void* data);
~SkThread_WinData();
HANDLE fHandle;
HANDLE fCancelEvent;
LPVOID fParam;
DWORD fThreadId;
SkThread::entryPointProc fEntryPoint;
bool fStarted;
};
#endif

View File

@ -6,10 +6,10 @@
*/
#include "SkRefCnt.h"
#include "SkThreadUtils.h"
#include "SkTypes.h"
#include "SkWeakRefCnt.h"
#include "Test.h"
#include <thread>
static void bounce_ref(void* data) {
SkRefCnt* ref = static_cast<SkRefCnt*>(data);
@ -22,11 +22,8 @@ static void bounce_ref(void* data) {
static void test_refCnt(skiatest::Reporter* reporter) {
SkRefCnt* ref = new SkRefCnt();
SkThread thing1(bounce_ref, ref);
SkThread thing2(bounce_ref, ref);
SkAssertResult(thing1.start());
SkAssertResult(thing2.start());
std::thread thing1(bounce_ref, ref);
std::thread thing2(bounce_ref, ref);
thing1.join();
thing2.join();
@ -55,15 +52,10 @@ static void bounce_weak_weak_ref(void* data) {
static void test_weakRefCnt(skiatest::Reporter* reporter) {
SkWeakRefCnt* ref = new SkWeakRefCnt();
SkThread thing1(bounce_ref, ref);
SkThread thing2(bounce_ref, ref);
SkThread thing3(bounce_weak_ref, ref);
SkThread thing4(bounce_weak_weak_ref, ref);
SkAssertResult(thing1.start());
SkAssertResult(thing2.start());
SkAssertResult(thing3.start());
SkAssertResult(thing4.start());
std::thread thing1(bounce_ref, ref);
std::thread thing2(bounce_ref, ref);
std::thread thing3(bounce_weak_ref, ref);
std::thread thing4(bounce_weak_weak_ref, ref);
thing1.join();
thing2.join();

View File

@ -8,8 +8,8 @@
#include <stdarg.h>
#include <stdio.h>
#include "SkString.h"
#include "SkThreadUtils.h"
#include "Test.h"
#include <thread>
// Windows vsnprintf doesn't 0-terminate safely), but is so far
// encapsulated in SkString that we can't test it directly.
@ -291,23 +291,16 @@ DEF_TEST(String_SkStrSplit_All, r) {
// https://bugs.chromium.org/p/skia/issues/detail?id=7107
DEF_TEST(String_Threaded, r) {
SkString gString("foo");
SkThread::entryPointProc readString = [](void* context) -> void {
SkString gStringCopy = *reinterpret_cast<SkString*>(context);
bool equals_string = gStringCopy.equals("test");
(void)equals_string;
};
SkThread threads[] = {
{readString, &gString},
{readString, &gString},
{readString, &gString},
{readString, &gString},
{readString, &gString},
};
for (SkThread& thread : threads) {
thread.start();
SkString str("foo");
std::thread threads[5];
for (auto& thread : threads) {
thread = std::thread([&] {
SkString copy = str;
(void)copy.equals("test");
});
}
for (SkThread& thread : threads) {
for (auto& thread : threads) {
thread.join();
}
}

View File

@ -5,14 +5,14 @@
* found in the LICENSE file.
*/
#include "SkAtomics.h"
#include "SkGraphics.h"
#include "SkPaint.h"
#include "SkTLS.h"
#include "SkThreadUtils.h"
#include "Test.h"
#include <atomic>
#include <thread>
static void thread_main(void*) {
static void thread_main() {
SkGraphics::SetTLSFontCacheLimit(1 * 1024 * 1024);
const char text[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
@ -31,41 +31,26 @@ static void thread_main(void*) {
}
}
static void test_threads(SkThread::entryPointProc proc) {
SkThread* threads[8];
int N = SK_ARRAY_COUNT(threads);
int i;
template <typename Fn>
static void test_threads(Fn fn) {
std::thread threads[8];
for (i = 0; i < N; ++i) {
threads[i] = new SkThread(proc);
for (auto& thread : threads) {
thread = std::thread(fn);
}
for (i = 0; i < N; ++i) {
threads[i]->start();
}
for (i = 0; i < N; ++i) {
threads[i]->join();
}
for (i = 0; i < N; ++i) {
delete threads[i];
for (auto& thread : threads) {
thread.join();
}
}
static int32_t gCounter;
static std::atomic<int> gCounter{0};
static void* FakeCreateTLS() {
sk_atomic_inc(&gCounter);
static void* fake_create_TLS() {
gCounter++;
return nullptr;
}
static void FakeDeleteTLS(void*) {
sk_atomic_dec(&gCounter);
}
static void testTLSDestructor(void*) {
SkTLS::Get(FakeCreateTLS, FakeDeleteTLS);
static void fake_delete_TLS(void*) {
gCounter--;
}
DEF_TEST(TLS, reporter) {
@ -76,6 +61,8 @@ DEF_TEST(TLS, reporter) {
// Test to ensure that at thread destruction, TLS destructors
// have been called.
test_threads(&testTLSDestructor);
REPORTER_ASSERT(reporter, 0 == gCounter);
test_threads([] {
SkTLS::Get(fake_create_TLS, fake_delete_TLS);
});
REPORTER_ASSERT(reporter, 0 == gCounter.load());
}