Skip to content

Instantly share code, notes, and snippets.

@roxlu
Created September 26, 2014 12:55
Show Gist options
  • Save roxlu/1c1af99f92bafff9d8d9 to your computer and use it in GitHub Desktop.
Save roxlu/1c1af99f92bafff9d8d9 to your computer and use it in GitHub Desktop.
Work in progress, simple cross platform mutex and threading code
cmake_minimum_required(VERSION 2.8.11)
set(bd ${CMAKE_CURRENT_LIST_DIR})
set(id ${bd})
include_directories(${id})
add_executable(test_thread test_thread.cpp)
if (WIN32)
else()
target_link_libraries(test_thread pthread)
endif()
#!/bin/sh
d=${PWD}
if [ ! -d ${d}/build ] ; then
mkdir ${d}/build
fi
cd ${d}/build
cmake ../
cmake --build . --config Release
if [ -d ${d}/build/Release ] ; then
cd ${d}/build/Release
./test_thread.exe
else
./test_thread
fi
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#if defined(__APPLE__)
# include <unistd.h>
#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 <windows.h>
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 <pthread.h>
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;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment