126 lines
3.8 KiB
C
126 lines
3.8 KiB
C
#ifndef INCLUDED_C_THREAD_H
|
|
#define INCLUDED_C_THREAD_H
|
|
|
|
#ifndef INCLUDED_C_TYPES_H
|
|
#include <c_Types.h>
|
|
#endif /*INCLUDED_C_TYPES_H*/
|
|
|
|
/* ------------------------------------------------------------------------------------------------------------------ */
|
|
/* */
|
|
|
|
typedef void* c_ThreadResult_t;
|
|
|
|
#if defined(_WIN32) || defined(_WIN64)
|
|
#include <windows.h>
|
|
#include <process.h>
|
|
typedef HANDLE c_Thread_t;
|
|
typedef DWORD c_ThreadId_t; // Windows 使用 DWORD 作为线程 ID
|
|
#define C_THREAD_FUNC_RETURN_TYPE unsigned __stdcall
|
|
#define C_THREAD_FUNC_RETURN_VTYPE unsigned
|
|
#else
|
|
#include <pthread.h>
|
|
typedef pthread_t c_Thread_t;
|
|
typedef unsigned long c_ThreadId_t; // POSIX 转换为数字 ID
|
|
#define C_THREAD_FUNC_RETURN_TYPE void*
|
|
#define C_THREAD_FUNC_RETURN_VTYPE C_THREAD_FUNC_RETURN_TYPE
|
|
#endif
|
|
|
|
// Universal thread creation signature
|
|
typedef C_THREAD_FUNC_RETURN_TYPE (*c_ThreadFn_t)(void*);
|
|
|
|
C_STATIC_FORCE_INLINE
|
|
c_bool_t c_Thread_Create(c_Thread_t* thread, c_ThreadFn_t func, void* arg) {
|
|
#if defined(_WIN32) || defined(_WIN64)
|
|
// *thread = CreateThread(NULL, 0, func, arg, 0, NULL);
|
|
// return (*thread != NULL);
|
|
*thread = (HANDLE)_beginthreadex(NULL, 0, (unsigned (__stdcall *)(void*))func, arg, 0, NULL);
|
|
return (*thread != NULL);
|
|
#else
|
|
return (pthread_create(thread, NULL, func, arg) == 0);
|
|
#endif
|
|
}
|
|
|
|
C_STATIC_FORCE_INLINE
|
|
void c_Thread_Join(c_Thread_t thread) {
|
|
#if defined(_WIN32) || defined(_WIN64)
|
|
WaitForSingleObject(thread, INFINITE);
|
|
CloseHandle(thread);
|
|
#else
|
|
pthread_join(thread, NULL);
|
|
#endif
|
|
}
|
|
|
|
C_STATIC_FORCE_INLINE
|
|
void c_Thread_Sleep(unsigned int milliseconds) {
|
|
#if defined(_WIN32) || defined(_WIN64)
|
|
Sleep(milliseconds);
|
|
#else
|
|
usleep(milliseconds * 1000);
|
|
#endif
|
|
}
|
|
|
|
C_STATIC_FORCE_INLINE
|
|
c_ThreadId_t c_Thread_SelfId(void) {
|
|
#if defined(_WIN32) || defined(_WIN64)
|
|
return GetCurrentThreadId();
|
|
#else
|
|
return (c_ThreadId_t)pthread_self();
|
|
#endif
|
|
}
|
|
|
|
C_STATIC_FORCE_INLINE
|
|
c_bool_t c_Thread_Detach(c_Thread_t thread) {
|
|
#if defined(_WIN32) || defined(_WIN64)
|
|
// Windows 中,关闭线程句柄并不等于终止线程。
|
|
// 它只是减少内核对象的引用计数。线程运行结束时,内核对象会自动销毁。
|
|
// 这与 POSIX 的 detach 行为完全一致。
|
|
if (thread != NULL) {
|
|
return (CloseHandle(thread) != 0);
|
|
}
|
|
return C_FALSE;
|
|
#else
|
|
// POSIX 直接使用 pthread_detach
|
|
return (pthread_detach(thread) == 0);
|
|
#endif
|
|
}
|
|
|
|
C_STATIC_FORCE_INLINE
|
|
c_bool_t c_Thread_Equal(c_Thread_t t1, c_Thread_t t2) {
|
|
#if defined(_WIN32) || defined(_WIN64)
|
|
// Windows 下可以通过比较线程 ID 来判断是否为同一个线程
|
|
// 即使其中一个是 GetCurrentThread() 产生的伪句柄,GetThreadId 也能正确识别
|
|
return (GetThreadId(t1) == GetThreadId(t2));
|
|
#else
|
|
// POSIX 提供专用的比较函数
|
|
return (pthread_equal(t1, t2) != 0);
|
|
#endif
|
|
}
|
|
|
|
C_STATIC_FORCE_INLINE
|
|
c_bool_t c_Thread_JoinWithResult(c_Thread_t thread, c_ThreadResult_t* out_result) {
|
|
#if defined(_WIN32) || defined(_WIN64)
|
|
if (WaitForSingleObject(thread, INFINITE) == WAIT_OBJECT_0) {
|
|
DWORD exit_code = 0;
|
|
if (GetExitCodeThread(thread, &exit_code)) {
|
|
if (out_result) {
|
|
// 将 DWORD 转换为指针类型输出
|
|
*out_result = (c_ThreadResult_t)(uintptr_t)exit_code;
|
|
}
|
|
CloseHandle(thread);
|
|
return C_TRUE;
|
|
}
|
|
}
|
|
CloseHandle(thread); // 即使失败也尝试关闭句柄
|
|
return C_FALSE;
|
|
#else
|
|
// POSIX 直接在 join 时传入指针变量的地址
|
|
return (pthread_join(thread, out_result) == 0);
|
|
#endif
|
|
}
|
|
|
|
#define c_Thread_Exit(x) return (C_THREAD_FUNC_RETURN_VTYPE)(x)
|
|
|
|
#define c_Thread_Fn(fn) C_THREAD_FUNC_RETURN_TYPE fn
|
|
|
|
#endif /*INCLUDED_C_THREAD_H*/
|