/*
 * 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_pthread.h"

#include <pthread.h>
#include <signal.h>

PThreadEvent::PThreadEvent() : fConditionFlag(false) {
    pthread_cond_init(&fCondition, nullptr);
    pthread_mutex_init(&fConditionMutex, nullptr);
}
PThreadEvent::~PThreadEvent() {
    pthread_mutex_destroy(&fConditionMutex);
    pthread_cond_destroy(&fCondition);
}
void PThreadEvent::trigger() {
    pthread_mutex_lock(&fConditionMutex);
    fConditionFlag = true;
    pthread_cond_signal(&fCondition);
    pthread_mutex_unlock(&fConditionMutex);
}
void PThreadEvent::wait() {
    pthread_mutex_lock(&fConditionMutex);
    while (!fConditionFlag) {
        pthread_cond_wait(&fCondition, &fConditionMutex);
    }
    pthread_mutex_unlock(&fConditionMutex);
}
bool PThreadEvent::isTriggered() {
    bool currentFlag;
    pthread_mutex_lock(&fConditionMutex);
    currentFlag = fConditionFlag;
    pthread_mutex_unlock(&fConditionMutex);
    return currentFlag;
}

SkThread_PThreadData::SkThread_PThreadData(SkThread::entryPointProc entryPoint, void* data)
    : fPThread()
    , fValidPThread(false)
    , fParam(data)
    , fEntryPoint(entryPoint)
{
    pthread_attr_init(&fAttr);
    pthread_attr_setdetachstate(&fAttr, PTHREAD_CREATE_JOINABLE);
}

SkThread_PThreadData::~SkThread_PThreadData() {
    pthread_attr_destroy(&fAttr);
}

static void* thread_start(void* arg) {
    SkThread_PThreadData* pthreadData = static_cast<SkThread_PThreadData*>(arg);
    // Wait for start signal
    pthreadData->fStarted.wait();

    // Call entry point only if thread was not canceled before starting.
    if (!pthreadData->fCanceled.isTriggered()) {
        pthreadData->fEntryPoint(pthreadData->fParam);
    }
    return nullptr;
}

SkThread::SkThread(entryPointProc entryPoint, void* data) {
    SkThread_PThreadData* pthreadData = new SkThread_PThreadData(entryPoint, data);
    fData = pthreadData;

    int ret = pthread_create(&(pthreadData->fPThread),
                             &(pthreadData->fAttr),
                             thread_start,
                             pthreadData);

    pthreadData->fValidPThread = (0 == ret);
}

SkThread::~SkThread() {
    if (fData != nullptr) {
        SkThread_PThreadData* pthreadData = static_cast<SkThread_PThreadData*>(fData);
        // If created thread but start was never called, kill the thread.
        if (pthreadData->fValidPThread && !pthreadData->fStarted.isTriggered()) {
            pthreadData->fCanceled.trigger();
            if (this->start()) {
                this->join();
            }
        }
        delete pthreadData;
    }
}

bool SkThread::start() {
    SkThread_PThreadData* pthreadData = static_cast<SkThread_PThreadData*>(fData);
    if (!pthreadData->fValidPThread) {
        return false;
    }

    if (pthreadData->fStarted.isTriggered()) {
        return false;
    }
    pthreadData->fStarted.trigger();
    return true;
}

void SkThread::join() {
    SkThread_PThreadData* pthreadData = static_cast<SkThread_PThreadData*>(fData);
    if (!pthreadData->fValidPThread || !pthreadData->fStarted.isTriggered()) {
        return;
    }

    pthread_join(pthreadData->fPThread, nullptr);
}
