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