aboutsummaryrefslogtreecommitdiffstats
path: root/src/zix
diff options
context:
space:
mode:
Diffstat (limited to 'src/zix')
-rw-r--r--src/zix/common.h135
-rw-r--r--src/zix/ring.c217
-rw-r--r--src/zix/ring.h141
-rw-r--r--src/zix/sem.h241
-rw-r--r--src/zix/thread.h131
5 files changed, 0 insertions, 865 deletions
diff --git a/src/zix/common.h b/src/zix/common.h
deleted file mode 100644
index cf07451..0000000
--- a/src/zix/common.h
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- Copyright 2016 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-
-#ifndef ZIX_COMMON_H
-#define ZIX_COMMON_H
-
-#include <stdbool.h>
-
-/**
- @addtogroup zix
- @{
-*/
-
-/** @cond */
-#ifdef ZIX_SHARED
-# ifdef _WIN32
-# define ZIX_LIB_IMPORT __declspec(dllimport)
-# define ZIX_LIB_EXPORT __declspec(dllexport)
-# else
-# define ZIX_LIB_IMPORT __attribute__((visibility("default")))
-# define ZIX_LIB_EXPORT __attribute__((visibility("default")))
-# endif
-# ifdef ZIX_INTERNAL
-# define ZIX_API ZIX_LIB_EXPORT
-# else
-# define ZIX_API ZIX_LIB_IMPORT
-# endif
-# define ZIX_PRIVATE static
-#elif defined(ZIX_INLINE)
-# define ZIX_API static inline
-# define ZIX_PRIVATE static inline
-#else
-# define ZIX_API
-# define ZIX_PRIVATE static
-#endif
-
-#ifdef __GNUC__
-# define ZIX_PURE_FUNC __attribute__((pure))
-# define ZIX_CONST_FUNC __attribute__((const))
-# define ZIX_MALLOC_FUNC __attribute__((malloc))
-#else
-# define ZIX_PURE_FUNC
-# define ZIX_CONST_FUNC
-# define ZIX_MALLOC_FUNC
-#endif
-
-#define ZIX_PURE_API ZIX_API ZIX_PURE_FUNC
-#define ZIX_CONST_API ZIX_API ZIX_CONST_FUNC
-#define ZIX_MALLOC_API ZIX_API ZIX_MALLOC_FUNC
-
-/** @endcond */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifdef __GNUC__
-#define ZIX_LOG_FUNC(fmt, arg1) __attribute__((format(printf, fmt, arg1)))
-#else
-#define ZIX_LOG_FUNC(fmt, arg1)
-#endif
-
-// Unused parameter macro to suppresses warnings and make it impossible to use
-#if defined(__cplusplus)
-# define ZIX_UNUSED(name)
-#elif defined(__GNUC__)
-# define ZIX_UNUSED(name) name##_unused __attribute__((__unused__))
-#else
-# define ZIX_UNUSED(name) name
-#endif
-
-typedef enum {
- ZIX_STATUS_SUCCESS,
- ZIX_STATUS_ERROR,
- ZIX_STATUS_NO_MEM,
- ZIX_STATUS_NOT_FOUND,
- ZIX_STATUS_EXISTS,
- ZIX_STATUS_BAD_ARG,
- ZIX_STATUS_BAD_PERMS
-} ZixStatus;
-
-static inline const char*
-zix_strerror(const ZixStatus status)
-{
- switch (status) {
- case ZIX_STATUS_SUCCESS: return "Success";
- case ZIX_STATUS_ERROR: return "Unknown error";
- case ZIX_STATUS_NO_MEM: return "Out of memory";
- case ZIX_STATUS_NOT_FOUND: return "Not found";
- case ZIX_STATUS_EXISTS: return "Exists";
- case ZIX_STATUS_BAD_ARG: return "Bad argument";
- case ZIX_STATUS_BAD_PERMS: return "Bad permissions";
- }
- return "Unknown error";
-}
-
-/**
- Function for comparing two elements.
-*/
-typedef int (*ZixComparator)(const void* a,
- const void* b,
- const void* user_data);
-
-/**
- Function for testing equality of two elements.
-*/
-typedef bool (*ZixEqualFunc)(const void* a, const void* b);
-
-/**
- Function to destroy an element.
-*/
-typedef void (*ZixDestroyFunc)(void* ptr);
-
-/**
- @}
-*/
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-#endif /* ZIX_COMMON_H */
diff --git a/src/zix/ring.c b/src/zix/ring.c
deleted file mode 100644
index e728a3f..0000000
--- a/src/zix/ring.c
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- Copyright 2011 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-
-#include "zix/ring.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-#ifdef HAVE_MLOCK
-# include <sys/mman.h>
-# define ZIX_MLOCK(ptr, size) mlock((ptr), (size))
-#elif defined(_WIN32)
-# include <windows.h>
-# define ZIX_MLOCK(ptr, size) VirtualLock((ptr), (size))
-#else
-# pragma message("warning: No memory locking, possible RT violations")
-# define ZIX_MLOCK(ptr, size)
-#endif
-
-#if defined(_MSC_VER)
-# include <windows.h>
-# define ZIX_READ_BARRIER() MemoryBarrier()
-# define ZIX_WRITE_BARRIER() MemoryBarrier()
-#elif defined(__GNUC__)
-# define ZIX_READ_BARRIER() __atomic_thread_fence(__ATOMIC_ACQUIRE)
-# define ZIX_WRITE_BARRIER() __atomic_thread_fence(__ATOMIC_RELEASE)
-#else
-# pragma message("warning: No memory barriers, possible SMP bugs")
-# define ZIX_READ_BARRIER()
-# define ZIX_WRITE_BARRIER()
-#endif
-
-struct ZixRingImpl {
- uint32_t write_head; ///< Read index into buf
- uint32_t read_head; ///< Write index into buf
- uint32_t size; ///< Size (capacity) in bytes
- uint32_t size_mask; ///< Mask for fast modulo
- char* buf; ///< Contents
-};
-
-static inline uint32_t
-next_power_of_two(uint32_t size)
-{
- // http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
- size--;
- size |= size >> 1u;
- size |= size >> 2u;
- size |= size >> 4u;
- size |= size >> 8u;
- size |= size >> 16u;
- size++;
- return size;
-}
-
-ZixRing*
-zix_ring_new(uint32_t size)
-{
- ZixRing* ring = (ZixRing*)malloc(sizeof(ZixRing));
- ring->write_head = 0;
- ring->read_head = 0;
- ring->size = next_power_of_two(size);
- ring->size_mask = ring->size - 1;
- ring->buf = (char*)malloc(ring->size);
- return ring;
-}
-
-void
-zix_ring_free(ZixRing* ring)
-{
- free(ring->buf);
- free(ring);
-}
-
-void
-zix_ring_mlock(ZixRing* ring)
-{
- ZIX_MLOCK(ring, sizeof(ZixRing));
- ZIX_MLOCK(ring->buf, ring->size);
-}
-
-void
-zix_ring_reset(ZixRing* ring)
-{
- ring->write_head = 0;
- ring->read_head = 0;
-}
-
-static inline uint32_t
-read_space_internal(const ZixRing* ring, uint32_t r, uint32_t w)
-{
- if (r < w) {
- return w - r;
- } else {
- return (w - r + ring->size) & ring->size_mask;
- }
-}
-
-uint32_t
-zix_ring_read_space(const ZixRing* ring)
-{
- return read_space_internal(ring, ring->read_head, ring->write_head);
-}
-
-static inline uint32_t
-write_space_internal(const ZixRing* ring, uint32_t r, uint32_t w)
-{
- if (r == w) {
- return ring->size - 1;
- } else if (r < w) {
- return ((r - w + ring->size) & ring->size_mask) - 1;
- } else {
- return (r - w) - 1;
- }
-}
-
-uint32_t
-zix_ring_write_space(const ZixRing* ring)
-{
- return write_space_internal(ring, ring->read_head, ring->write_head);
-}
-
-uint32_t
-zix_ring_capacity(const ZixRing* ring)
-{
- return ring->size - 1;
-}
-
-static inline uint32_t
-peek_internal(const ZixRing* ring, uint32_t r, uint32_t w,
- uint32_t size, void* dst)
-{
- if (read_space_internal(ring, r, w) < size) {
- return 0;
- }
-
- if (r + size < ring->size) {
- memcpy(dst, &ring->buf[r], size);
- } else {
- const uint32_t first_size = ring->size - r;
- memcpy(dst, &ring->buf[r], first_size);
- memcpy((char*)dst + first_size, &ring->buf[0], size - first_size);
- }
-
- return size;
-}
-
-uint32_t
-zix_ring_peek(ZixRing* ring, void* dst, uint32_t size)
-{
- return peek_internal(ring, ring->read_head, ring->write_head, size, dst);
-}
-
-uint32_t
-zix_ring_read(ZixRing* ring, void* dst, uint32_t size)
-{
- const uint32_t r = ring->read_head;
- const uint32_t w = ring->write_head;
-
- if (peek_internal(ring, r, w, size, dst)) {
- ZIX_READ_BARRIER();
- ring->read_head = (r + size) & ring->size_mask;
- return size;
- }
-
- return 0;
-}
-
-uint32_t
-zix_ring_skip(ZixRing* ring, uint32_t size)
-{
- const uint32_t r = ring->read_head;
- const uint32_t w = ring->write_head;
- if (read_space_internal(ring, r, w) < size) {
- return 0;
- }
-
- ZIX_READ_BARRIER();
- ring->read_head = (r + size) & ring->size_mask;
- return size;
-}
-
-uint32_t
-zix_ring_write(ZixRing* ring, const void* src, uint32_t size)
-{
- const uint32_t r = ring->read_head;
- const uint32_t w = ring->write_head;
- if (write_space_internal(ring, r, w) < size) {
- return 0;
- }
-
- if (w + size <= ring->size) {
- memcpy(&ring->buf[w], src, size);
- ZIX_WRITE_BARRIER();
- ring->write_head = (w + size) & ring->size_mask;
- } else {
- const uint32_t this_size = ring->size - w;
- memcpy(&ring->buf[w], src, this_size);
- memcpy(&ring->buf[0], (const char*)src + this_size, size - this_size);
- ZIX_WRITE_BARRIER();
- ring->write_head = size - this_size;
- }
-
- return size;
-}
diff --git a/src/zix/ring.h b/src/zix/ring.h
deleted file mode 100644
index 99437f8..0000000
--- a/src/zix/ring.h
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- Copyright 2011-2014 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-
-#ifndef ZIX_RING_H
-#define ZIX_RING_H
-
-#include "zix/common.h"
-
-#include <stdint.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- @addtogroup zix
- @{
- @name Ring
- @{
-*/
-
-/**
- A lock-free ring buffer.
-
- Thread-safe with a single reader and single writer, and realtime safe
- on both ends.
-*/
-typedef struct ZixRingImpl ZixRing;
-
-/**
- Create a new ring.
- @param size Size in bytes (note this may be rounded up).
-
- At most `size` - 1 bytes may be stored in the ring at once.
-*/
-ZIX_MALLOC_API
-ZixRing*
-zix_ring_new(uint32_t size);
-
-/**
- Destroy a ring.
-*/
-ZIX_API
-void
-zix_ring_free(ZixRing* ring);
-
-/**
- Lock the ring data into physical memory.
-
- This function is NOT thread safe or real-time safe, but it should be called
- after zix_ring_new() to lock all ring memory to avoid page faults while
- using the ring (i.e. this function MUST be called first in order for the
- ring to be truly real-time safe).
-
-*/
-ZIX_API
-void
-zix_ring_mlock(ZixRing* ring);
-
-/**
- Reset (empty) a ring.
-
- This function is NOT thread-safe, it may only be called when there are no
- readers or writers.
-*/
-ZIX_API
-void
-zix_ring_reset(ZixRing* ring);
-
-/**
- Return the number of bytes of space available for reading.
-*/
-ZIX_CONST_API
-uint32_t
-zix_ring_read_space(const ZixRing* ring);
-
-/**
- Return the number of bytes of space available for writing.
-*/
-ZIX_CONST_API
-uint32_t
-zix_ring_write_space(const ZixRing* ring);
-
-/**
- Return the capacity (i.e. total write space when empty).
-*/
-ZIX_CONST_API
-uint32_t
-zix_ring_capacity(const ZixRing* ring);
-
-/**
- Read from the ring without advancing the read head.
-*/
-ZIX_API
-uint32_t
-zix_ring_peek(ZixRing* ring, void* dst, uint32_t size);
-
-/**
- Read from the ring and advance the read head.
-*/
-ZIX_API
-uint32_t
-zix_ring_read(ZixRing* ring, void* dst, uint32_t size);
-
-/**
- Skip data in the ring (advance read head without reading).
-*/
-ZIX_API
-uint32_t
-zix_ring_skip(ZixRing* ring, uint32_t size);
-
-/**
- Write data to the ring.
-*/
-ZIX_API
-uint32_t
-zix_ring_write(ZixRing* ring, const void* src, uint32_t size);
-
-/**
- @}
- @}
-*/
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-#endif /* ZIX_RING_H */
diff --git a/src/zix/sem.h b/src/zix/sem.h
deleted file mode 100644
index 7ced8dc..0000000
--- a/src/zix/sem.h
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- Copyright 2012-2014 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-
-#ifndef ZIX_SEM_H
-#define ZIX_SEM_H
-
-#include "zix/common.h"
-
-#ifdef __APPLE__
-# include <mach/mach.h>
-#elif defined(_WIN32)
-# include <limits.h>
-# include <windows.h>
-#else
-# include <errno.h>
-# include <semaphore.h>
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stdbool.h>
-
-/**
- @addtogroup zix
- @{
- @name Semaphore
- @{
-*/
-
-struct ZixSemImpl;
-
-/**
- A counting semaphore.
-
- This is an integer that is always positive, and has two main operations:
- increment (post) and decrement (wait). If a decrement can not be performed
- (i.e. the value is 0) the caller will be blocked until another thread posts
- and the operation can succeed.
-
- Semaphores can be created with any starting value, but typically this will
- be 0 so the semaphore can be used as a simple signal where each post
- corresponds to one wait.
-
- Semaphores are very efficient (much moreso than a mutex/cond pair). In
- particular, at least on Linux, post is async-signal-safe, which means it
- does not block and will not be interrupted. If you need to signal from
- a realtime thread, this is the most appropriate primitive to use.
-*/
-typedef struct ZixSemImpl ZixSem;
-
-/**
- Create and initialize `sem` to `initial`.
-*/
-static inline ZixStatus
-zix_sem_init(ZixSem* sem, unsigned initial);
-
-/**
- Destroy `sem`.
-*/
-static inline void
-zix_sem_destroy(ZixSem* sem);
-
-/**
- Increment (and signal any waiters).
- Realtime safe.
-*/
-static inline void
-zix_sem_post(ZixSem* sem);
-
-/**
- Wait until count is > 0, then decrement.
- Obviously not realtime safe.
-*/
-static inline ZixStatus
-zix_sem_wait(ZixSem* sem);
-
-/**
- Non-blocking version of wait().
-
- @return true if decrement was successful (lock was acquired).
-*/
-static inline bool
-zix_sem_try_wait(ZixSem* sem);
-
-/**
- @cond
-*/
-
-#ifdef __APPLE__
-
-struct ZixSemImpl {
- semaphore_t sem;
-};
-
-static inline ZixStatus
-zix_sem_init(ZixSem* sem, unsigned val)
-{
- return semaphore_create(mach_task_self(), &sem->sem, SYNC_POLICY_FIFO, val)
- ? ZIX_STATUS_ERROR : ZIX_STATUS_SUCCESS;
-}
-
-static inline void
-zix_sem_destroy(ZixSem* sem)
-{
- semaphore_destroy(mach_task_self(), sem->sem);
-}
-
-static inline void
-zix_sem_post(ZixSem* sem)
-{
- semaphore_signal(sem->sem);
-}
-
-static inline ZixStatus
-zix_sem_wait(ZixSem* sem)
-{
- if (semaphore_wait(sem->sem) != KERN_SUCCESS) {
- return ZIX_STATUS_ERROR;
- }
- return ZIX_STATUS_SUCCESS;
-}
-
-static inline bool
-zix_sem_try_wait(ZixSem* sem)
-{
- const mach_timespec_t zero = { 0, 0 };
- return semaphore_timedwait(sem->sem, zero) == KERN_SUCCESS;
-}
-
-#elif defined(_WIN32)
-
-struct ZixSemImpl {
- HANDLE sem;
-};
-
-static inline ZixStatus
-zix_sem_init(ZixSem* sem, unsigned initial)
-{
- sem->sem = CreateSemaphore(NULL, initial, LONG_MAX, NULL);
- return (sem->sem) ? ZIX_STATUS_SUCCESS : ZIX_STATUS_ERROR;
-}
-
-static inline void
-zix_sem_destroy(ZixSem* sem)
-{
- CloseHandle(sem->sem);
-}
-
-static inline void
-zix_sem_post(ZixSem* sem)
-{
- ReleaseSemaphore(sem->sem, 1, NULL);
-}
-
-static inline ZixStatus
-zix_sem_wait(ZixSem* sem)
-{
- if (WaitForSingleObject(sem->sem, INFINITE) != WAIT_OBJECT_0) {
- return ZIX_STATUS_ERROR;
- }
- return ZIX_STATUS_SUCCESS;
-}
-
-static inline bool
-zix_sem_try_wait(ZixSem* sem)
-{
- return WaitForSingleObject(sem->sem, 0) == WAIT_OBJECT_0;
-}
-
-#else /* !defined(__APPLE__) && !defined(_WIN32) */
-
-struct ZixSemImpl {
- sem_t sem;
-};
-
-static inline ZixStatus
-zix_sem_init(ZixSem* sem, unsigned initial)
-{
- return sem_init(&sem->sem, 0, initial)
- ? ZIX_STATUS_ERROR : ZIX_STATUS_SUCCESS;
-}
-
-static inline void
-zix_sem_destroy(ZixSem* sem)
-{
- sem_destroy(&sem->sem);
-}
-
-static inline void
-zix_sem_post(ZixSem* sem)
-{
- sem_post(&sem->sem);
-}
-
-static inline ZixStatus
-zix_sem_wait(ZixSem* sem)
-{
- while (sem_wait(&sem->sem)) {
- if (errno != EINTR) {
- return ZIX_STATUS_ERROR;
- }
- /* Otherwise, interrupted, so try again. */
- }
-
- return ZIX_STATUS_SUCCESS;
-}
-
-static inline bool
-zix_sem_try_wait(ZixSem* sem)
-{
- return (sem_trywait(&sem->sem) == 0);
-}
-
-#endif
-
-/**
- @endcond
- @}
- @}
-*/
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-#endif /* ZIX_SEM_H */
diff --git a/src/zix/thread.h b/src/zix/thread.h
deleted file mode 100644
index dbfdf36..0000000
--- a/src/zix/thread.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- Copyright 2012-2014 David Robillard <d@drobilla.net>
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
-
- THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-
-#ifndef ZIX_THREAD_H
-#define ZIX_THREAD_H
-
-#include "zix/common.h"
-
-#ifdef _WIN32
-# include <windows.h>
-#else
-# include <errno.h>
-# include <pthread.h>
-#endif
-
-#include <stddef.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- @addtogroup zix
- @{
- @name Thread
- @{
-*/
-
-#ifdef _WIN32
-typedef HANDLE ZixThread;
-#else
-typedef pthread_t ZixThread;
-#endif
-
-/**
- Initialize `thread` to a new thread.
-
- The thread will immediately be launched, calling `function` with `arg`
- as the only parameter.
-*/
-static inline ZixStatus
-zix_thread_create(ZixThread* thread,
- size_t stack_size,
- void* (*function)(void*),
- void* arg);
-
-/**
- Join `thread` (block until `thread` exits).
-*/
-static inline ZixStatus
-zix_thread_join(ZixThread thread, void** retval);
-
-#ifdef _WIN32
-
-static inline ZixStatus
-zix_thread_create(ZixThread* thread,
- size_t stack_size,
- void* (*function)(void*),
- void* arg)
-{
- *thread = CreateThread(NULL, stack_size,
- (LPTHREAD_START_ROUTINE)function, arg,
- 0, NULL);
- return *thread ? ZIX_STATUS_SUCCESS : ZIX_STATUS_ERROR;
-}
-
-static inline ZixStatus
-zix_thread_join(ZixThread thread, void** retval)
-{
- (void)retval;
-
- return WaitForSingleObject(thread, INFINITE)
- ? ZIX_STATUS_SUCCESS : ZIX_STATUS_ERROR;
-}
-
-#else /* !defined(_WIN32) */
-
-static inline ZixStatus
-zix_thread_create(ZixThread* thread,
- size_t stack_size,
- void* (*function)(void*),
- void* arg)
-{
- pthread_attr_t attr;
- pthread_attr_init(&attr);
- pthread_attr_setstacksize(&attr, stack_size);
-
- const int ret = pthread_create(thread, NULL, function, arg);
- pthread_attr_destroy(&attr);
-
- switch (ret) {
- case EAGAIN: return ZIX_STATUS_NO_MEM;
- case EINVAL: return ZIX_STATUS_BAD_ARG;
- case EPERM: return ZIX_STATUS_BAD_PERMS;
- }
-
- return ret ? ZIX_STATUS_ERROR : ZIX_STATUS_SUCCESS;
-}
-
-static inline ZixStatus
-zix_thread_join(ZixThread thread, void** retval)
-{
- return pthread_join(thread, retval)
- ? ZIX_STATUS_ERROR : ZIX_STATUS_SUCCESS;
-}
-
-#endif
-
-/**
- @}
- @}
-*/
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-#endif /* ZIX_THREAD_H */