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 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 28 SkThread_WinData::~SkThread_WinData() { 29 CloseHandle(fCancelEvent); 30 } 31 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 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 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 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 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