Home | History | Annotate | Download | only in utils
      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