• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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