diff options
-rw-r--r-- | BUILD.gn | 2 | ||||
-rw-r--r-- | bench/nanobench.cpp | 27 | ||||
-rw-r--r-- | dm/DM.cpp | 1 | ||||
-rw-r--r-- | gn/utils.gni | 3 | ||||
-rw-r--r-- | public.bzl | 1 | ||||
-rw-r--r-- | src/core/SkExecutor.cpp | 15 | ||||
-rw-r--r-- | src/utils/SkThreadUtils.h | 39 | ||||
-rw-r--r-- | src/utils/SkThreadUtils_pthread.cpp | 116 | ||||
-rw-r--r-- | src/utils/SkThreadUtils_pthread.h | 43 | ||||
-rw-r--r-- | src/utils/SkThreadUtils_win.cpp | 100 | ||||
-rw-r--r-- | src/utils/SkThreadUtils_win.h | 27 | ||||
-rw-r--r-- | tests/RefCntTest.cpp | 22 | ||||
-rw-r--r-- | tests/StringTest.cpp | 27 | ||||
-rw-r--r-- | tests/TLSTest.cpp | 51 |
14 files changed, 65 insertions, 409 deletions
@@ -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", diff --git a/bench/nanobench.cpp b/bench/nanobench.cpp index c5dfe0cf7f..550e0b7744 100644 --- a/bench/nanobench.cpp +++ b/bench/nanobench.cpp @@ -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) { @@ -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" diff --git a/gn/utils.gni b/gn/utils.gni index 54e7f4443d..8bcf4ee7d1 100644 --- a/gn/utils.gni +++ b/gn/utils.gni @@ -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 diff --git a/public.bzl b/public.bzl index d66781b534..3cd08fee6a 100644 --- a/public.bzl +++ b/public.bzl @@ -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/*", diff --git a/src/core/SkExecutor.cpp b/src/core/SkExecutor.cpp index d37431eabb..eb0412a55e 100644 --- a/src/core/SkExecutor.cpp +++ b/src/core/SkExecutor.cpp @@ -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) { diff --git a/src/utils/SkThreadUtils.h b/src/utils/SkThreadUtils.h deleted file mode 100644 index d9fc99d397..0000000000 --- a/src/utils/SkThreadUtils.h +++ /dev/null @@ -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 diff --git a/src/utils/SkThreadUtils_pthread.cpp b/src/utils/SkThreadUtils_pthread.cpp index 0bd804d43a..ae4db9ae55 100644 --- a/src/utils/SkThreadUtils_pthread.cpp +++ b/src/utils/SkThreadUtils_pthread.cpp @@ -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. diff --git a/src/utils/SkThreadUtils_pthread.h b/src/utils/SkThreadUtils_pthread.h deleted file mode 100644 index 3e1020275c..0000000000 --- a/src/utils/SkThreadUtils_pthread.h +++ /dev/null @@ -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 diff --git a/src/utils/SkThreadUtils_win.cpp b/src/utils/SkThreadUtils_win.cpp index 0da339aa84..ae4db9ae55 100644 --- a/src/utils/SkThreadUtils_win.cpp +++ b/src/utils/SkThreadUtils_win.cpp @@ -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. diff --git a/src/utils/SkThreadUtils_win.h b/src/utils/SkThreadUtils_win.h deleted file mode 100644 index b1de4816cf..0000000000 --- a/src/utils/SkThreadUtils_win.h +++ /dev/null @@ -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 diff --git a/tests/RefCntTest.cpp b/tests/RefCntTest.cpp index 4bad342cee..1a100b549c 100644 --- a/tests/RefCntTest.cpp +++ b/tests/RefCntTest.cpp @@ -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(); diff --git a/tests/StringTest.cpp b/tests/StringTest.cpp index 91ef009edd..166637fd65 100644 --- a/tests/StringTest.cpp +++ b/tests/StringTest.cpp @@ -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(); } } diff --git a/tests/TLSTest.cpp b/tests/TLSTest.cpp index 2702d9c000..0fadd7ed9c 100644 --- a/tests/TLSTest.cpp +++ b/tests/TLSTest.cpp @@ -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()); } |