#include "core/thread/Thread.hpp"

#include <string.h>

static void reset(thrd_t& t) {
    memset(&t, 0, sizeof(thrd_t));
}

Core::Thread::Thread() : thread() {
    reset(thread);
}

Core::Thread::Thread(Thread&& other) : thread() {
    swap(other);
}

static bool doesExist(thrd_t& t) {
    thrd_t zero{};
    return memcmp(&zero, &t, sizeof(thrd_t)) != 0;
}

Core::Thread::~Thread() {
    if(doesExist(thread)) {
        (void)join(nullptr);
    }
}

Core::Thread& Core::Thread::operator=(Thread&& other) {
    if(this != &other) {
        if(doesExist(thread)) {
            (void)join(nullptr);
        }
        reset(thread);
        swap(other);
    }
    return *this;
}

cbool Core::Thread::start(Function f, void* p) {
    if(doesExist(thread)) {
        return true;
    }
    return thrd_create(&thread, f, p) != thrd_success;
}

cbool Core::Thread::join(int* returnValue) {
    int e = thrd_join(thread, returnValue);
    reset(thread);
    return e != thrd_success;
}

void Core::Thread::swap(Thread& other) {
    thrd_t tmp;
    memcpy(&tmp, &thread, sizeof(thrd_t));
    memcpy(&thread, &other.thread, sizeof(thrd_t));
    memcpy(&other.thread, &tmp, sizeof(thrd_t));
}