blob: 0da339aa849978d0238cec13ec1754eb7f1076a6 [file] [log] [blame]
bungeman@google.com55487522012-05-14 14:09:24 +00001/*
2 * Copyright 2012 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "SkTypes.h"
mtklein1ee76512015-11-02 10:20:27 -08009#if defined(SK_BUILD_FOR_WIN32)
bungeman@google.com55487522012-05-14 14:09:24 +000010
11#include "SkThreadUtils.h"
12#include "SkThreadUtils_win.h"
13
14SkThread_WinData::SkThread_WinData(SkThread::entryPointProc entryPoint, void* data)
halcanary96fcdcc2015-08-27 07:41:13 -070015 : fHandle(nullptr)
bungeman@google.com55487522012-05-14 14:09:24 +000016 , fParam(data)
17 , fThreadId(0)
18 , fEntryPoint(entryPoint)
19 , fStarted(false)
20{
21 fCancelEvent = CreateEvent(
halcanary96fcdcc2015-08-27 07:41:13 -070022 nullptr, // default security attributes
bungeman@google.com55487522012-05-14 14:09:24 +000023 false, //auto reset
24 false, //not signaled
halcanary96fcdcc2015-08-27 07:41:13 -070025 nullptr); //no name
bungeman@google.com55487522012-05-14 14:09:24 +000026}
27
28SkThread_WinData::~SkThread_WinData() {
29 CloseHandle(fCancelEvent);
30}
31
32static DWORD WINAPI thread_start(LPVOID data) {
33 SkThread_WinData* winData = static_cast<SkThread_WinData*>(data);
34
35 //See if this thread was canceled before starting.
36 if (WaitForSingleObject(winData->fCancelEvent, 0) == WAIT_OBJECT_0) {
37 return 0;
38 }
39
40 winData->fEntryPoint(winData->fParam);
41 return 0;
42}
43
44SkThread::SkThread(entryPointProc entryPoint, void* data) {
45 SkThread_WinData* winData = new SkThread_WinData(entryPoint, data);
46 fData = winData;
47
halcanary96fcdcc2015-08-27 07:41:13 -070048 if (nullptr == winData->fCancelEvent) {
bungeman@google.com55487522012-05-14 14:09:24 +000049 return;
50 }
51
52 winData->fHandle = CreateThread(
halcanary96fcdcc2015-08-27 07:41:13 -070053 nullptr, // default security attributes
bungeman@google.com55487522012-05-14 14:09:24 +000054 0, // use default stack size
55 thread_start, // thread function name (proxy)
56 winData, // argument to thread function (proxy args)
mtkleina1bde7d2015-10-20 11:05:06 -070057 CREATE_SUSPENDED, // we used to set processor affinity, which needed this
bungeman@google.com55487522012-05-14 14:09:24 +000058 &winData->fThreadId); // returns the thread identifier
59}
60
61SkThread::~SkThread() {
halcanary96fcdcc2015-08-27 07:41:13 -070062 if (fData != nullptr) {
bungeman@google.com55487522012-05-14 14:09:24 +000063 SkThread_WinData* winData = static_cast<SkThread_WinData*>(fData);
64 // If created thread but start was never called, kill the thread.
halcanary96fcdcc2015-08-27 07:41:13 -070065 if (winData->fHandle != nullptr && !winData->fStarted) {
bungeman@google.com55487522012-05-14 14:09:24 +000066 if (SetEvent(winData->fCancelEvent) != 0) {
67 if (this->start()) {
68 this->join();
69 }
70 } else {
71 //kill with prejudice
72 TerminateThread(winData->fHandle, -1);
73 }
74 }
75 delete winData;
76 }
77}
78
79bool SkThread::start() {
80 SkThread_WinData* winData = static_cast<SkThread_WinData*>(fData);
halcanary96fcdcc2015-08-27 07:41:13 -070081 if (nullptr == winData->fHandle) {
bungeman@google.com55487522012-05-14 14:09:24 +000082 return false;
83 }
84
85 if (winData->fStarted) {
86 return false;
87 }
88 winData->fStarted = -1 != ResumeThread(winData->fHandle);
89 return winData->fStarted;
90}
91
92void SkThread::join() {
93 SkThread_WinData* winData = static_cast<SkThread_WinData*>(fData);
halcanary96fcdcc2015-08-27 07:41:13 -070094 if (nullptr == winData->fHandle || !winData->fStarted) {
bungeman@google.com55487522012-05-14 14:09:24 +000095 return;
96 }
97
98 WaitForSingleObject(winData->fHandle, INFINITE);
99}
mtklein1ee76512015-11-02 10:20:27 -0800100
101#endif//defined(SK_BUILD_FOR_WIN32)