From 73847e5708c3a8b33de5b767101cdabd9020a686 Mon Sep 17 00:00:00 2001 From: zzy <2450266535@qq.com> Date: Mon, 23 Oct 2023 13:21:02 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9B=E5=BB=BAtthread=E4=B8=AD=E7=9A=84thre?= =?UTF-8?q?ad=E5=92=8Cmutex?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 4 +- test/thread/CMakeLists.txt | 15 +++++ test/thread/thread.c | 39 +++++++++++++ tthread.h | 116 ++++++++++++++++++++++++++++++++++--- 4 files changed, 164 insertions(+), 10 deletions(-) create mode 100644 test/thread/CMakeLists.txt create mode 100644 test/thread/thread.c diff --git a/.gitignore b/.gitignore index 7000632..c801c31 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,6 @@ !test/client/client.c !test/client/CMakeLists.txt !test/server/server.c -!test/server/CMakeLists.txt \ No newline at end of file +!test/server/CMakeLists.txt +!test/thread/thread.c +!test/thread/CMakeLists.txt \ No newline at end of file diff --git a/test/thread/CMakeLists.txt b/test/thread/CMakeLists.txt new file mode 100644 index 0000000..8c221b7 --- /dev/null +++ b/test/thread/CMakeLists.txt @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 3.22.1) + +project(thread) + +set(EXECUTABLE_OUTPUT_PATH ../) +set(CMAKE_C_STANDARD 99) +set(SRC_FILE thread.c) + +add_executable(${PROJECT_NAME} ${SRC_FILE}) + +if(WIN32) + target_link_libraries(${PROJECT_NAME} wsock32 ws2_32) +endif() +# cmake .. +# cmake --build . \ No newline at end of file diff --git a/test/thread/thread.c b/test/thread/thread.c new file mode 100644 index 0000000..4380cf1 --- /dev/null +++ b/test/thread/thread.c @@ -0,0 +1,39 @@ +#include +#include +#include "../../tthread.h" + +MUTEX mutex; + +void work(void* arg) { + int* num = (int*)arg; + for (int i = 0; i < 100; i++) { + thread_mutex_lock(mutex); + printf("%d => %d\n", 1, (*num)++); + thread_mutex_unlock(mutex); + } +} + +int main() +{ + int res; + TID tid; + int num = 0; + if (thread_mutex_init(&mutex) != 0) { + return -1; + } + if (thread_create(&tid, work, &num) != 0) { + return -2; + } + for (int i = 0; i < 100; i++) { + thread_mutex_lock(mutex); + printf("%d => %d\n", 0, num++); + thread_mutex_unlock(mutex); + } + res = thread_join(tid); + if (res != 0) { + //res = GetLastError(); + return res; + } + + return 0; +} \ No newline at end of file diff --git a/tthread.h b/tthread.h index 56c4696..1db5067 100644 --- a/tthread.h +++ b/tthread.h @@ -3,15 +3,21 @@ #include "sysenv.h" #if _OS_WIN -#include -#define TID LPDWORD - +//#include +//#include +//#include +//#define INFINITE 0xFFFFFFFF // Infinite timeout +//#define WAIT_FAILED ((DWORD)0xFFFFFFFF) +//#include +#include +typedef DWORD TID; +typedef HANDLE MUTEX; +typedef HANDLE COND; #elif _OS_LINUX -#include #include -#include #define TID pthread_t - +#define MUTEX pthread_mutex_t +#define COND pthread_cond_t #else #error "Not Supported Operator System" #endif @@ -20,13 +26,105 @@ extern "C" { #endif +enum { + ERR_THREAD_SUCCESS, -static inline void tthread_create(TID* tid,void(*thread_func)(void*), void* data) { + ERR_THREAD_CREATE, + ERR_THREAD_JOIN, + ERR_THREAD_WIN_CLOSE_HANDLE, + ERR_THREAD_WIN_OPEN_THREAD, + + ERR_THREAD_MUTEX_INIT, + ERR_THREAD_MUTEX_DESTROY, + ERR_THREAD_MUTEX_LOCK, + ERR_THREAD_MUTEX_UNLOCK, + + ERR_THREAD_COND_INIT, + ERR_THREAD_COND_DESTROY, + ERR_THREAD_COND_SINGAL, + ERR_THREAD_COND_BROADCAST, + ERR_THREAD_COND_WAIT, + ERR_THREAD_COND_TIMEDWAIT, + + ERR_THREAD_ENUM_END +}; + +static inline int thread_create(TID* tid, void(*start_routine)(void*), void* arg); +static inline void thread_exit(void); +static inline int thread_join(TID tid); + +static inline int thread_mutex_init(MUTEX* mutex); +static inline int thread_mutex_destory(MUTEX mutex); +static inline int thread_mutex_lock(MUTEX mutex); +static inline int thread_mutex_unlock(MUTEX mutex); + +static inline int thread_create(TID* tid, void(*start_routine)(void*), void* arg) { #if _OS_WIN - CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)thread_func, data, 0, tid); + HANDLE h = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)start_routine, arg, 0, tid); + if (h == NULL) { return ERR_THREAD_CREATE; } + if (!CloseHandle(h)) { return ERR_THREAD_WIN_CLOSE_HANDLE; } #elif _OS_LINUX - pthread_create(tid, 0, (void*(*)(void*))thread_func, data); + if (pthread_create(tid, NULL, start_routine, arg) != 0) { return ERR_THREAD_CREATE; } #endif + return ERR_THREAD_SUCCESS; +} + +static inline void thread_exit(void) { +#if _OS_WIN + ThreadExit(0); +#elif _OS_LINUX + pthread_exit(NULL); +#endif +} + +static inline int thread_join(TID tid) { +#if _OS_WIN + HANDLE h = OpenThread(THREAD_ALL_ACCESS, 0, tid); + if (h == NULL) { return ERR_THREAD_WIN_OPEN_THREAD; } + if (WaitForSingleObject(h, INFINITE) == WAIT_FAILED) { return ERR_THREAD_JOIN; } + if (!CloseHandle(h)) { return ERR_THREAD_WIN_CLOSE_HANDLE; } +#elif _OS_LINUX + if (pthread_join(tid, NULL) != 0) { return ERR_THREAD_JOIN; } +#endif + return ERR_THREAD_SUCCESS; +} + +// mutex part +static inline int thread_mutex_init(MUTEX* mutex) { +#if _OS_WIN + *mutex = CreateMutex(NULL, FALSE, NULL); + if (*mutex == NULL) { return ERR_THREAD_MUTEX_INIT; } +#elif _OS_LINUX + if (pthread_mutex_init() != 0) { return ERR_THREAD_MUTEX_INIT; } +#endif + return ERR_THREAD_SUCCESS; +} + +static inline int thread_mutex_destory(MUTEX mutex) { +#if _OS_WIN + if (!CloseHandle(mutex)) { return ERR_THREAD_MUTEX_DESTROY; } +#elif _OS_LINUX + if (pthread_mutex_destroy(mutex) != 0) { return ERR_THREAD_MUTEX_DESTROY; } +#endif + ERR_THREAD_SUCCESS; +} + +static inline int thread_mutex_lock(MUTEX mutex) { +#if _OS_WIN + if (WaitForSingleObject(mutex, INFINITE) == WAIT_FAILED) { return ERR_THREAD_MUTEX_LOCK; } +#elif _OS_LINUX + if (pthread_mutex_lock(mutex) != 0) { return ERR_THREAD_MUTEX_LOCK; } +#endif + return ERR_THREAD_SUCCESS; +} + +static inline int thread_mutex_unlock(MUTEX mutex) { +#if _OS_WIN + ReleaseMutex(mutex); +#elif _OS_LINUX + if (pthread_mutex_unlock(mutex) != 0) { return ERR_THREAD_MUTEX_UNLOCK; } +#endif + return ERR_THREAD_SUCCESS; } #ifdef __cplusplus