| /* | |
| * 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" | |
| #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) |