1 /*
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"
9 #if defined(SK_BUILD_FOR_WIN32)
10
11 #include "SkThreadUtils.h"
12 #include "SkThreadUtils_win.h"
13
SkThread_WinData(SkThread::entryPointProc entryPoint,void * data)14 SkThread_WinData::SkThread_WinData(SkThread::entryPointProc entryPoint, void* data)
15 : fHandle(nullptr)
16 , fParam(data)
17 , fThreadId(0)
18 , fEntryPoint(entryPoint)
19 , fStarted(false)
20 {
21 fCancelEvent = CreateEvent(
22 nullptr, // default security attributes
23 false, //auto reset
24 false, //not signaled
25 nullptr); //no name
26 }
27
~SkThread_WinData()28 SkThread_WinData::~SkThread_WinData() {
29 CloseHandle(fCancelEvent);
30 }
31
thread_start(LPVOID data)32 static 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
SkThread(entryPointProc entryPoint,void * data)44 SkThread::SkThread(entryPointProc entryPoint, void* data) {
45 SkThread_WinData* winData = new SkThread_WinData(entryPoint, data);
46 fData = winData;
47
48 if (nullptr == winData->fCancelEvent) {
49 return;
50 }
51
52 winData->fHandle = CreateThread(
53 nullptr, // default security attributes
54 0, // use default stack size
55 thread_start, // thread function name (proxy)
56 winData, // argument to thread function (proxy args)
57 CREATE_SUSPENDED, // we used to set processor affinity, which needed this
58 &winData->fThreadId); // returns the thread identifier
59 }
60
~SkThread()61 SkThread::~SkThread() {
62 if (fData != nullptr) {
63 SkThread_WinData* winData = static_cast<SkThread_WinData*>(fData);
64 // If created thread but start was never called, kill the thread.
65 if (winData->fHandle != nullptr && !winData->fStarted) {
66 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
start()79 bool SkThread::start() {
80 SkThread_WinData* winData = static_cast<SkThread_WinData*>(fData);
81 if (nullptr == winData->fHandle) {
82 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
join()92 void SkThread::join() {
93 SkThread_WinData* winData = static_cast<SkThread_WinData*>(fData);
94 if (nullptr == winData->fHandle || !winData->fStarted) {
95 return;
96 }
97
98 WaitForSingleObject(winData->fHandle, INFINITE);
99 }
100
101 #endif//defined(SK_BUILD_FOR_WIN32)
102