/*
 * thread_utils.c - 跨平台线程封装实现
 * - Windows: _beginthreadex / WaitForSingleObject / CloseHandle
 * - Linux:   pthread_create / pthread_join
 */

#include "thread_utils.h"
#include <stdint.h>   /* uintptr_t，用于 Windows 线程句柄转换 */
#include <stdlib.h>   /* malloc / free */
#ifdef _WIN32
#include <process.h>  /* _beginthreadex */
#endif

#ifdef _WIN32
/*
 * Windows 线程入口：__stdcall，参数为 Thread_Create 传入的包装结构体指针
 * 从结构中取出用户函数与参数，释放结构体后调用用户函数
 */
static unsigned int __stdcall thread_wrapper(void* arg)
{
    struct {
        thread_fn_t fn;
        void* arg;
    }* p = (void*)arg;
    thread_fn_t fn = p->fn;    /* 用户提供的线程函数 */
    void* fn_arg = p->arg;     /* 传给用户函数的参数 */
    free(p);                   /* 包装结构体仅在此处使用，用完即释 */
    fn(fn_arg);                /* 调用用户线程函数 */
    return 0;                  /* _beginthreadex 要求返回 unsigned int */
}
#else
/*
 * Linux 线程入口：参数为 Thread_Create 传入的包装结构体指针
 * 从结构中取出用户函数与参数，释放结构体后调用用户函数
 */
static void* thread_wrapper(void* arg)
{
    struct {
        thread_fn_t fn;
        void* arg;
    }* p = arg;
    thread_fn_t fn = p->fn;
    void* fn_arg = p->arg;
    free(p);
    fn(fn_arg);
    return NULL;               /* pthread 入口要求返回 void* */
}
#endif

/*
 * 创建新线程，在新线程中执行 fn(arg)
 *
 * fn:         线程函数，类型 void fn(void* arg)
 * arg:        传给 fn 的参数，由调用方保证在线程使用期间有效
 * out_handle: 输出线程句柄，用于后续 Thread_Join 等待
 *
 * 返回: 0 成功，-1 失败（参数无效、malloc 失败或系统创建线程失败）
 */
int Thread_Create(thread_fn_t fn, void* arg, thread_handle_t* out_handle)
{
    if (!fn || !out_handle)
        return -1;
    /* 在堆上分配包装结构，因线程启动前就返回，线程入口需要独立副本 */
    struct {
        thread_fn_t fn;
        void* arg;
    }* p = malloc(sizeof(*p));
    if (!p)
        return -1;
    p->fn = fn;
    p->arg = arg;

#ifdef _WIN32
    {
        uintptr_t t = _beginthreadex(NULL, 0, thread_wrapper, p, 0, NULL);
        if (t == 0) {          /* 0 表示创建失败 */
            free(p);
            return -1;
        }
        *out_handle = (HANDLE)(uintptr_t)t;  /* 保存句柄供 Thread_Join 使用 */
    }
#else
    if (pthread_create(out_handle, NULL, thread_wrapper, p) != 0) {
        free(p);
        return -1;
    }
#endif
    return 0;
}

/*
 * 等待指定线程结束，并释放系统资源
 *
 * handle: Thread_Create 返回的线程句柄
 *         Windows 下会 CloseHandle，之后 handle 不可再使用
 */
void Thread_Join(thread_handle_t handle)
{
#ifdef _WIN32
    if (handle != NULL && handle != (HANDLE)0)
        WaitForSingleObject(handle, INFINITE);  /* 阻塞直到线程退出 */
    if (handle != NULL && handle != (HANDLE)0)
        CloseHandle(handle);                    /* 释放线程内核对象 */
#else
    pthread_join(handle, NULL);  /* 阻塞直到线程退出，不取返回值 */
#endif
}
