/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkTypes.h"

#include "SkThreadUtils.h"
#include "SkThreadUtils_win.h"

SkThread_WinData::SkThread_WinData(SkThread::entryPointProc entryPoint, void* data)
    : fHandle(nullptr)
    , fParam(data)
    , fThreadId(0)
    , fEntryPoint(entryPoint)
    , fStarted(false)
{
    fCancelEvent = CreateEvent(
        nullptr,  // default security attributes
        false, //auto reset
        false, //not signaled
        nullptr); //no name
}

SkThread_WinData::~SkThread_WinData() {
    CloseHandle(fCancelEvent);
}

static DWORD WINAPI thread_start(LPVOID data) {
    SkThread_WinData* winData = static_cast<SkThread_WinData*>(data);

    //See if this thread was canceled before starting.
    if (WaitForSingleObject(winData->fCancelEvent, 0) == WAIT_OBJECT_0) {
        return 0;
    }

    winData->fEntryPoint(winData->fParam);
    return 0;
}

SkThread::SkThread(entryPointProc entryPoint, void* data) {
    SkThread_WinData* winData = new SkThread_WinData(entryPoint, data);
    fData = winData;

    if (nullptr == winData->fCancelEvent) {
        return;
    }

    winData->fHandle = CreateThread(
        nullptr,                   // default security attributes
        0,                      // use default stack size
        thread_start,           // thread function name (proxy)
        winData,                // argument to thread function (proxy args)
        CREATE_SUSPENDED,       // we used to set processor affinity, which needed this
        &winData->fThreadId);   // returns the thread identifier
}

SkThread::~SkThread() {
    if (fData != nullptr) {
        SkThread_WinData* winData = static_cast<SkThread_WinData*>(fData);
        // If created thread but start was never called, kill the thread.
        if (winData->fHandle != nullptr && !winData->fStarted) {
            if (SetEvent(winData->fCancelEvent) != 0) {
                if (this->start()) {
                    this->join();
                }
            } else {
                //kill with prejudice
                TerminateThread(winData->fHandle, -1);
            }
        }
        delete winData;
    }
}

bool SkThread::start() {
    SkThread_WinData* winData = static_cast<SkThread_WinData*>(fData);
    if (nullptr == winData->fHandle) {
        return false;
    }

    if (winData->fStarted) {
        return false;
    }
    winData->fStarted = -1 != ResumeThread(winData->fHandle);
    return winData->fStarted;
}

void SkThread::join() {
    SkThread_WinData* winData = static_cast<SkThread_WinData*>(fData);
    if (nullptr == winData->fHandle || !winData->fStarted) {
        return;
    }

    WaitForSingleObject(winData->fHandle, INFINITE);
}
