/*
 * Copyright (c) 1994, 2021 Alex Leigh, All Rights Reserved
 *
 * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF ALEX LEIGH The copyright
 * notice above does not evidence any actual or intended publication of such
 * source code.
 *
 * Disclosure, copying, distribution, or transmission of this code without
 * express permission is prohibited.
 */

#include <mecha.h>

void mFthr_sleep(int ms) {
    Sleep(ms);
}

/**
 * Free resources associated with the given thread.
 *
 * Calling this function will not terminate the thread, if it is running.
 */
void mFthr_free(struct mSthr *thread) {
    // NOP
}

/**
 * Create a new thread of execution.
 *
 * Returns MECHA_OK on success, otherwise, returns MECHA_ERR.
 */
int mFthr_create(struct mSthr *thread, void (*func)(void *)) {
    DWORD tid;
    // Our func is a safe cast here, because we ignore the return value.
    thread->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) func, NULL, 0, &tid);
    return MECHA_OK;
}

/**
 * Wait for the given thread to terminate.
 *
 * Returns MECHA_OK on success, otherwise, returns MECHA_ERR. If MECHA_ERR is returned, the state of the joined
 * thread is indeterminate.
 *
 * @param thread
 * @return MECHA_OK on success, MECHA_ERR on error.
 */
int mFthr_join(struct mSthr *thread) {
    WaitForSingleObject(thread->thread, INFINITE);
    return MECHA_OK;
}


int mFthr_mutex_init(struct mSthr_mutex *mutex) {
    mutex->mutex = CreateMutex(NULL, FALSE, NULL);
    if (mutex->mutex == NULL) return MECHA_ERR;
    return MECHA_OK;
}

int mFthr_mutex_unlock(struct mSthr_mutex *mutex) {
    if (!ReleaseMutex(mutex->mutex)) return MECHA_ERR;
    return MECHA_OK;
}

int mFthr_mutex_lock(struct mSthr_mutex *mutex) {
    DWORD dwWaitResult = WaitForSingleObject(mutex->mutex, INFINITE);
    if (dwWaitResult == WAIT_OBJECT_0) return MECHA_OK;
    return MECHA_ERR;
}

void mFthr_mutex_free(struct mSthr_mutex *mutex) {
    CloseHandle(mutex->mutex);
}


