Initial commit, yay
This commit is contained in:
commit
25e26756cd
85 changed files with 7077 additions and 0 deletions
4
src/threading/CMakeLists.txt
Normal file
4
src/threading/CMakeLists.txt
Normal file
|
@ -0,0 +1,4 @@
|
|||
add_library(threading STATIC os_mutex.c
|
||||
os_rwlock.c
|
||||
os_semaphore.c
|
||||
os_thread.c)
|
61
src/threading/os_mutex.c
Normal file
61
src/threading/os_mutex.c
Normal file
|
@ -0,0 +1,61 @@
|
|||
#include "os_mutex.h"
|
||||
|
||||
|
||||
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) // Fuck you, apple
|
||||
|
||||
int OSMutex_Create(os_mutex_t* target)
|
||||
{
|
||||
return pthread_mutex_init(target, NULL);
|
||||
}
|
||||
|
||||
int OSMutex_Acquire(os_mutex_t* mutex)
|
||||
{
|
||||
return pthread_mutex_lock(mutex);
|
||||
}
|
||||
|
||||
int OSMutex_Release(os_mutex_t* mutex)
|
||||
{
|
||||
return pthread_mutex_unlock(mutex);
|
||||
}
|
||||
|
||||
int OSMutex_Destroy(os_mutex_t* mutex)
|
||||
{
|
||||
return pthread_mutex_destroy(mutex);
|
||||
}
|
||||
|
||||
#elif defined(_WIN32)
|
||||
|
||||
int OSMutex_Create(os_mutex_t* target)
|
||||
{
|
||||
target[0] = CreateMutex(
|
||||
NULL, // default security attributes
|
||||
FALSE, // initially not owned
|
||||
NULL); // unnamed mutex
|
||||
if (target[0] == NULL) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int OSMutex_Acquire(os_mutex_t* mutex)
|
||||
{
|
||||
WaitForSingleObject(
|
||||
*mutex, // handle to mutex
|
||||
INFINITE); // no time-out interval
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int OSMutex_Release(os_mutex_t* mutex)
|
||||
{
|
||||
return ReleaseMutex(mutex);
|
||||
}
|
||||
|
||||
int OSMutex_Destroy(os_mutex_t* mutex)
|
||||
{
|
||||
CloseHandle(mutex[0]);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
#endif
|
23
src/threading/os_mutex.h
Normal file
23
src/threading/os_mutex.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
#ifndef OS_MUTEX_H
|
||||
#define OS_MUTEX_H
|
||||
|
||||
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) // Fuck you, apple
|
||||
|
||||
#include <pthread.h>
|
||||
typedef pthread_mutex_t os_mutex_t;
|
||||
|
||||
#elif defined(_WIN32)
|
||||
|
||||
#include <windows.h>
|
||||
typedef HANDLE os_mutex_t;
|
||||
|
||||
#else
|
||||
#error "Unknown Threading Standard, feel free to add support via a fork/PR"
|
||||
#endif
|
||||
|
||||
int OSMutex_Create(os_mutex_t* target);
|
||||
int OSMutex_Acquire(os_mutex_t* mutex);
|
||||
int OSMutex_Release(os_mutex_t* mutex);
|
||||
int OSMutex_Destroy(os_mutex_t* mutex);
|
||||
|
||||
#endif
|
90
src/threading/os_rwlock.c
Normal file
90
src/threading/os_rwlock.c
Normal file
|
@ -0,0 +1,90 @@
|
|||
#include "os_rwlock.h"
|
||||
#include <pthread.h>
|
||||
|
||||
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) // Fuck you, apple
|
||||
|
||||
int OSRWLock_Create(OSRWLock* target)
|
||||
{
|
||||
return pthread_rwlock_init(target, NULL);
|
||||
}
|
||||
|
||||
void OSRWLock_Destroy(OSRWLock* rwlock)
|
||||
{
|
||||
pthread_rwlock_destroy(rwlock);
|
||||
}
|
||||
|
||||
int OSRWLock_Read(OSRWLock* rwlock)
|
||||
{
|
||||
return pthread_rwlock_rdlock(rwlock);
|
||||
}
|
||||
|
||||
int OSRWLock_Write(OSRWLock* rwlock)
|
||||
{
|
||||
return pthread_rwlock_wrlock(rwlock);
|
||||
}
|
||||
|
||||
int OSRWLock_ReleaseRead(OSRWLock* rwlock)
|
||||
{
|
||||
return pthread_rwlock_unlock(rwlock);
|
||||
}
|
||||
|
||||
int OSRWLock_ReleaseWrite(OSRWLock* rwlock)
|
||||
{
|
||||
return pthread_rwlock_unlock(rwlock);
|
||||
}
|
||||
|
||||
#elif defined(_WIN32)
|
||||
|
||||
int OSRWLock_Create(OSRWLock* target)
|
||||
{
|
||||
InitializeSRWLock(*target);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
void OSRWLock_Destroy(OSRWLock* rwlock)
|
||||
{
|
||||
// Win32 Locks can be forgotten if there are no more threads waiting on it
|
||||
OSRWLock_Write(*rwlock);
|
||||
// Now, nobody else can be holding the lock
|
||||
OSRWLock_ReleaseWrite(*rwlock);
|
||||
|
||||
// Forget about it
|
||||
return;
|
||||
}
|
||||
|
||||
int OSRWLock_Read(OSRWLock* rwlock)
|
||||
{
|
||||
AcquireSRWLockShared(*rwlock);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int OSRWLock_Write(OSRWLock* rwlock)
|
||||
{
|
||||
AcquireSRWLockExclusive(*rwlock);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int OSRWLock_ReleaseRead(OSRWLock* rwlock)
|
||||
{
|
||||
ReleaseSRWLockShared(*rwlock);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int OSRWLock_ReleaseWrite(OSRWLock* rwlock)
|
||||
{
|
||||
ReleaseSRWLockExclusive(*rwlock);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
|
||||
#error "Threading standard not supported"
|
||||
|
||||
#endif
|
29
src/threading/os_rwlock.h
Normal file
29
src/threading/os_rwlock.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
#ifndef UTILITIEC_RWLOCK_H
|
||||
#define UTILITIEC_RWLOCK_H
|
||||
|
||||
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) // Fuck you, apple
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
typedef pthread_rwlock_t OSRWLock;
|
||||
|
||||
|
||||
#elif defined(_WIN32)
|
||||
#include <syncapi.h>
|
||||
|
||||
typedef PSRWLOCK OSRWLock;
|
||||
|
||||
#else
|
||||
#error "Threading standard not supported"
|
||||
|
||||
#endif
|
||||
|
||||
int OSRWLock_Create(OSRWLock* target);
|
||||
void OSRWLock_Destroy(OSRWLock* rwlock);
|
||||
|
||||
int OSRWLock_Read(OSRWLock* rwlock);
|
||||
int OSRWLock_Write(OSRWLock* rwlock);
|
||||
int OSRWLock_ReleaseRead(OSRWLock* rwlock);
|
||||
int OSRWLock_ReleaseWrite(OSRWLock* rwlock);
|
||||
|
||||
#endif
|
92
src/threading/os_semaphore.c
Normal file
92
src/threading/os_semaphore.c
Normal file
|
@ -0,0 +1,92 @@
|
|||
#include "os_semaphore.h"
|
||||
#include <semaphore.h>
|
||||
|
||||
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) // Fuck you, apple
|
||||
|
||||
int OSSemaphore_Create(os_semaphore_t* target, unsigned int value)
|
||||
{
|
||||
return sem_init(
|
||||
target,
|
||||
0, // multi-threaded, not multiprocess
|
||||
value
|
||||
);
|
||||
}
|
||||
|
||||
int OSSemaphore_GetValue(os_semaphore_t* semaphore)
|
||||
{
|
||||
int count;
|
||||
sem_getvalue(semaphore, &count);
|
||||
return count;
|
||||
}
|
||||
|
||||
int OSSemaphore_Wait(os_semaphore_t* semaphore)
|
||||
{
|
||||
return sem_wait(semaphore);
|
||||
}
|
||||
|
||||
int OSSemaphore_Release(os_semaphore_t* semaphore)
|
||||
{
|
||||
return sem_post(semaphore);
|
||||
}
|
||||
|
||||
void OSSemaphore_Destroy(os_semaphore_t* semaphore)
|
||||
{
|
||||
sem_close(semaphore);
|
||||
return;
|
||||
}
|
||||
|
||||
#elif defined(_WIN32)
|
||||
|
||||
int OSSemaphore_Create(os_semaphore_t* target, unsigned int value)
|
||||
{
|
||||
target->sem_handle = CreateSemaphoreA(
|
||||
SEMAPHORE_ALL_ACCESS, // Access attributes
|
||||
value, // InitialCount
|
||||
32 767, // POSIX_SEM_VALUE_MAX
|
||||
NULL // Named semaphore
|
||||
);
|
||||
if (target->sem_handle != NULL) {
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
|
||||
target->count = value;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int OSSemaphore_GetValue(os_semaphore_t* semaphore)
|
||||
{
|
||||
return semaphore->count;
|
||||
}
|
||||
|
||||
int OSSempahore_Wait(os_semaphore_t* semaphore)
|
||||
{
|
||||
DWORD r = WaitForSingleObject(
|
||||
semaphore->sem_handle,
|
||||
INIFINITE
|
||||
);
|
||||
semaphore->count -= 1;
|
||||
return r != WAIT_FAILED;
|
||||
}
|
||||
|
||||
int OSSempahore_Release(os_semaphore_t* semaphore)
|
||||
{
|
||||
if (ReleaseSemaphore(
|
||||
semaphore->sem_handle,
|
||||
1,
|
||||
NULL
|
||||
)) {
|
||||
semaphore->count++;
|
||||
return EXIT_SUCCESS;
|
||||
} else {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
void OSSemaphore_Destroy(os_semaphore_t* semaphore)
|
||||
{
|
||||
CloseHandle(semaphore->sem_handle);
|
||||
}
|
||||
|
||||
#endif
|
59
src/threading/os_semaphore.h
Normal file
59
src/threading/os_semaphore.h
Normal file
|
@ -0,0 +1,59 @@
|
|||
#ifndef OS_SEMAPHORE_H
|
||||
#define OS_SEMAPHORE_H
|
||||
|
||||
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) // Fuck you, apple
|
||||
|
||||
#include <semaphore.h>
|
||||
typedef sem_t os_semaphore_t;
|
||||
|
||||
#elif defined(_WIN32)
|
||||
|
||||
#include <windows.h>
|
||||
typedef struct Struct_OSSemaphore {
|
||||
atomic int count;
|
||||
HANDLE sem_handle;
|
||||
} os_semaphore_t;
|
||||
|
||||
#else
|
||||
#error "Unknown Threading Standard, feel free to add support via a fork/PR"
|
||||
#endif
|
||||
|
||||
/*!
|
||||
@brief Create a Operating-System-Backed Semaphore
|
||||
@param target Memory area for the semaphore
|
||||
@param initialValue Value the semaphore will initially hold
|
||||
@pre target must be a valid pointer
|
||||
@return EXIT_SUCCESS, ENOMEM
|
||||
*/
|
||||
int OSSemaphore_Create(os_semaphore_t* target, unsigned int initialValue);
|
||||
|
||||
/*!
|
||||
@brief Rertieve the value of the semaphore
|
||||
@param semaphore this
|
||||
@pre Must be a valid semaphore
|
||||
@return the value of the semaphore, negative if there are threads waiting
|
||||
*/
|
||||
int OSSemaphore_GetValue(os_semaphore_t* semaphore);
|
||||
|
||||
/*!
|
||||
@brief Wait for a resource to be available on the semaphore
|
||||
@param semaphore this
|
||||
@return EXIT_SUCCESS, EINVAL, EINTR
|
||||
*/
|
||||
int OSSemaphore_Wait(os_semaphore_t* semaphore);
|
||||
|
||||
/*!
|
||||
@brief Signal the release of a resource on the semaphore
|
||||
@param semaphore this
|
||||
@return EINVAL, EOVERFLOW
|
||||
*/
|
||||
int OSSemaphore_Release(os_semaphore_t* semaphore);
|
||||
|
||||
/*!
|
||||
@brief Destroy the referenced semaphore resource and return it to the OS
|
||||
@param semaphore this
|
||||
@return void
|
||||
*/
|
||||
void OSSemaphore_Destroy(os_semaphore_t* semaphore);
|
||||
|
||||
#endif
|
89
src/threading/os_thread.c
Normal file
89
src/threading/os_thread.c
Normal file
|
@ -0,0 +1,89 @@
|
|||
#include "os_thread.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
|
||||
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
|
||||
int OSThread_Create(os_thread_t* destination, ThreadFunction subroutine, void* arg)
|
||||
{
|
||||
return pthread_create(destination, NULL, subroutine, arg);
|
||||
}
|
||||
|
||||
int OSThread_Kill(os_thread_t* thread)
|
||||
{
|
||||
return pthread_cancel(*thread);
|
||||
}
|
||||
|
||||
int OSThread_Join(os_thread_t* thread, void** thread_return)
|
||||
{
|
||||
return pthread_join(*thread, thread_return);
|
||||
}
|
||||
|
||||
int OSThread_Destroy(os_thread_t* thread)
|
||||
{
|
||||
(void) thread;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
#elif defined _WIN32
|
||||
|
||||
struct CaptureReturnArgument {
|
||||
ThreadFunction subroutine;
|
||||
void* arg;
|
||||
void** return_value_storage;
|
||||
};
|
||||
static void capture_return(struct CaptureReturnArgument* a)
|
||||
{
|
||||
a.return_value_storage[0] = a->subroutine(a->arg);
|
||||
return;
|
||||
}
|
||||
|
||||
int OSThread_Create(os_thread_t* destination, ThreadFunction subroutine, void* arg)
|
||||
{
|
||||
destination->return_value_storage = malloc(sizeof(void*));
|
||||
if (destination->return_value_storage == NULL) {
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
destination->return_value_storage[0] = NULL;
|
||||
destination->handle = CreateThread(
|
||||
THREAD_ALL_ACCESS, // Security
|
||||
0, // default stack size
|
||||
capture_return, // start address
|
||||
arg, // argument
|
||||
0, // start immediately
|
||||
NULL // thread id receeiver
|
||||
);
|
||||
if (destination->handle == NULL) {
|
||||
return GetLastError();
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int OSThread_Kill(os_thread_t* thread)
|
||||
{
|
||||
return 1 == TerminateThread(
|
||||
thread->thread_handle,
|
||||
0 // exit code
|
||||
);
|
||||
}
|
||||
|
||||
int OSThread_Join(os_thread_t* thread, void** thread_return)
|
||||
{
|
||||
WaitForSingleObject(thread->thread_handle, INFINITE);
|
||||
thread_return[0] = thread->return_value_storage[0];
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int OSThread_Destroy(os_thread_t* thread)
|
||||
{
|
||||
free(thread->return_value_storage);
|
||||
CloseHandle(thread->thread_handle);
|
||||
}
|
||||
|
||||
#endif
|
28
src/threading/os_thread.h
Normal file
28
src/threading/os_thread.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
#ifndef OS_THREAD_H
|
||||
#define OS_THREAD_H
|
||||
|
||||
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) // Fuck you, apple
|
||||
|
||||
#include <pthread.h>
|
||||
typedef pthread_t os_thread_t;
|
||||
|
||||
#elif defined(_WIN32)
|
||||
|
||||
#include <windows.h>
|
||||
typedef struct Struct_OSThread {
|
||||
HANDLE thread_handle;
|
||||
void** return_value_storage;
|
||||
} os_thread_t;
|
||||
|
||||
#else
|
||||
#error "Unknown Threading Standard, feel free to add support via a fork/PR"
|
||||
#endif
|
||||
|
||||
typedef void* (*ThreadFunction) (void* arg);
|
||||
|
||||
int OSThread_Create(os_thread_t* destination, ThreadFunction subroutine, void* arg);
|
||||
int OSThread_Kill(os_thread_t* thread);
|
||||
int OSThread_Join(os_thread_t* thread, void** thread_return);
|
||||
int OSThread_Destroy(os_thread_t* thread);
|
||||
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue