#include #include #include #include #if defined(__APPLE__) # include #endif /* ----------------------------------------------------------------------------------- */ struct thread; /* forward declared */ struct mutex; /* forward declared */ typedef void*(*thread_function)(void* param); thread* thread_alloc(thread_function func, void* param); int thread_free(thread* t); int thread_join(thread* t); int mutex_init(mutex* m); int mutex_destroy(mutex* m); int mutex_lock(mutex* m); int mutex_unlock(mutex* m); /* ----------------------------------------------------------------------------------- */ int thread_free(thread* t) { if (NULL == t) { return -1; } free(t); return 0; } #if defined(_WIN32) #define WIN32_LEAN_AND_MEAN #include struct thread { HANDLE handle; DWORD thread_id; thread_function func; void* user; }; struct mutex { HANDLE handle; }; typedef struct thread; typedef struct mutex; DWORD WINAPI thread_wrapper_function(LPVOID param); /* -- */ DWORD WINAPI thread_wrapper_function(LPVOID param) { thread* handle = (thread*)param; if (NULL == handle) { return 0; } if (NULL == handle->func) { return 0; } handle->func(handle->user); return 0; } thread* thread_alloc(thread_function func, void* param) { thread* t = (thread*)malloc(sizeof(thread)); if (NULL == t) { return NULL; } if (NULL == func) { return NULL; } t->user = param; t->handle = CreateThread(NULL, 0, thread_wrapper_function, t, 0, &t->thread_id); t->func = func; if (NULL == t->handle) { free(t); t = NULL; } return t; } int thread_join(thread* t) { if (NULL == t) { return -1; } DWORD r = WaitForSingleObject(t->handle, INFINITE); if (WAIT_OBJECT_0 == r) { return 0 ; } else if (WAIT_ABANDONED == r) { return -2; } else if (WAIT_FAILED) { return -3; } return 0; } int mutex_init(mutex* m) { if (NULL == m) { return -1; } m->handle = CreateMutex(NULL, FALSE, NULL); /* default security, not owned by calling thread, unnamed. */ if (NULL == m->handle) { return -2; } return 0; } int mutex_destroy(mutex* m) { if (NULL == m) { return -1; } if (0 == CloseHandle(m->handle)) { return -2; } return 0; } int mutex_lock(mutex* m) { if (NULL == m) { return -1; } DWORD r = WaitForSingleObject(m->handle, INFINITE); if (WAIT_OBJECT_0 == r) { return 0 ; } else if (WAIT_ABANDONED == r) { return -2; } return 0; } int mutex_unlock(mutex* m) { if (NULL == m) { return -1; } if (!ReleaseMutex(m->handle)) { return -2; } return 0; } #elif defined(__linux) or defined(__APPLE__) # include struct thread { pthread_t handle; thread_function func; void* user; }; struct mutex { pthread_mutex_t handle; }; typedef struct thread thread; typedef struct mutex mutex; void* thread_function_wrapper(void* t); /* --- */ void* thread_function_wrapper(void* t) { thread* handle = (thread*)t; if (NULL == handle) { return NULL; } handle->func(handle->user); return NULL; } thread* thread_alloc(thread_function func, void* param) { thread* t; int r; if (NULL == func) { return NULL; } t = (thread*)malloc(sizeof(thread)); if (!t) { return NULL; } t->func = func; t->user = param; r = pthread_create(&t->handle, NULL, thread_function_wrapper, (void*)t); if (0 != r) { free(t); t = NULL; return NULL; } return t; } int mutex_init(mutex* m) { if (NULL == m) { return -1; } if (0 != pthread_mutex_init(&m->handle, NULL)) { return -2; } return 0; } int mutex_destroy(mutex* m) { if (NULL == m) { return -1; } if (0 != pthread_mutex_destroy(&m->handle)) { return -2; } return 0; } int mutex_lock(mutex* m) { if (NULL == m) { return -1; } if (0 != pthread_mutex_lock(&m->handle)) { return -2; } return 0; } int mutex_unlock(mutex* m) { if (NULL == m) { return -1; } if (0 != pthread_mutex_unlock(&m->handle)) { return -2; } return 0; } int thread_join(thread* t) { if (NULL == t) { return -1; } if (0 != pthread_join(t->handle, NULL)) { return -2; } return 0; } #endif /* -------------------------------------------------------------------------------- */ static void* my_thread_function(void* p); static void sigh(int s); /* -------------------------------------------------------------------------------- */ mutex my_mutex; int shared_data = 0; bool must_run = true; int main() { printf("\n\ntest_threading\n\n"); signal(SIGINT, sigh); /* Create a test thread. */ thread* t = thread_alloc(my_thread_function, NULL); if (NULL == t) { printf("Cannot create thread.\n"); exit(1); } /* create the mutex. */ if (0 != mutex_init(&my_mutex)) { printf("Cannot create mutex.\n"); exit(1); } /* Loop a couple of times, join the thread. */ int c = 0; while (must_run) { if (c % 10) { printf("+ Count: %d\n", c); } if (3 == c) { printf("+ Joining `my_thread_fuction`.\n"); thread_join(t); } mutex_lock(&my_mutex); printf("+ Shared data: %d\n", shared_data); mutex_unlock(&my_mutex); ++c; #if defined(__APPLE__) or defined(__linux) usleep(1e6); #elif defined(_WIN32) Sleep(1e3); #endif } thread_free(t); t = NULL; return 0; } /* -------------------------------------------------------------------------------- */ static void sigh(int s) { printf("Got signal.\n"); must_run = false; } static void* my_thread_function(void* p) { printf(">>My thread function!\n"); int c = 0; while (true) { /* Change the shared data. */ mutex_lock(&my_mutex); shared_data++; mutex_unlock(&my_mutex); printf(">> My Thread Function Loop! Shared data: %d\n", shared_data); #if defined(__APPLE__) or defined(__linux) usleep(50e4); #else defined(_WIN32) Sleep(500); #endif c++; if (c > 10) { printf(">> My Thread Function will stop.\n"); break; } } printf(">> My Thread Function stopped.\n"); return NULL; }