/*
* This file is part of libplacebo.
*
* libplacebo is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* libplacebo is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with libplacebo. If not, see .
*/
#pragma once
#include
#include
#include
#include
#include
typedef pthread_mutex_t pl_mutex;
typedef pthread_cond_t pl_cond;
typedef pthread_mutex_t pl_static_mutex;
typedef pthread_t pl_thread;
#define PL_STATIC_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
static inline int pl_mutex_init_type_internal(pl_mutex *mutex, enum pl_mutex_type mtype)
{
int mutex_type;
switch (mtype) {
case PL_MUTEX_RECURSIVE:
mutex_type = PTHREAD_MUTEX_RECURSIVE;
break;
case PL_MUTEX_NORMAL:
default:
#ifndef NDEBUG
mutex_type = PTHREAD_MUTEX_ERRORCHECK;
#else
mutex_type = PTHREAD_MUTEX_DEFAULT;
#endif
break;
}
int ret = 0;
pthread_mutexattr_t attr;
ret = pthread_mutexattr_init(&attr);
if (ret != 0)
return ret;
pthread_mutexattr_settype(&attr, mutex_type);
ret = pthread_mutex_init(mutex, &attr);
pthread_mutexattr_destroy(&attr);
return ret;
}
#define pl_mutex_init_type(mutex, mtype) \
pl_assert(!pl_mutex_init_type_internal(mutex, mtype))
#define pl_mutex_destroy pthread_mutex_destroy
#define pl_mutex_lock pthread_mutex_lock
#define pl_mutex_unlock pthread_mutex_unlock
static inline int pl_cond_init(pl_cond *cond)
{
int ret = 0;
pthread_condattr_t attr;
ret = pthread_condattr_init(&attr);
if (ret != 0)
return ret;
#ifdef PTHREAD_HAS_SETCLOCK
pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
#endif
ret = pthread_cond_init(cond, &attr);
pthread_condattr_destroy(&attr);
return ret;
}
#define pl_cond_destroy pthread_cond_destroy
#define pl_cond_broadcast pthread_cond_broadcast
#define pl_cond_signal pthread_cond_signal
#define pl_cond_wait pthread_cond_wait
static inline int pl_cond_timedwait(pl_cond *cond, pl_mutex *mutex, uint64_t timeout)
{
if (timeout == UINT64_MAX)
return pthread_cond_wait(cond, mutex);
struct timespec ts;
#ifdef PTHREAD_HAS_SETCLOCK
if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0)
return errno;
#else
struct timeval tv;
if (gettimeofday(&tv, NULL) < 0) // equivalent to CLOCK_REALTIME
return errno;
ts.tv_sec = tv.tv_sec;
ts.tv_nsec = tv.tv_usec * 1000;
#endif
ts.tv_sec += timeout / 1000000000LLU;
ts.tv_nsec += timeout % 1000000000LLU;
if (ts.tv_nsec > 1000000000L) {
ts.tv_nsec -= 1000000000L;
ts.tv_sec++;
}
return pthread_cond_timedwait(cond, mutex, &ts);
}
#define pl_static_mutex_lock pthread_mutex_lock
#define pl_static_mutex_unlock pthread_mutex_unlock
#define PL_THREAD_VOID void *
#define PL_THREAD_RETURN() return NULL
#define pl_thread_create(t, f, a) pthread_create(t, NULL, f, a)
#define pl_thread_join(t) pthread_join(t, NULL)
static inline bool pl_thread_sleep(double t)
{
if (t <= 0.0)
return true;
struct timespec ts;
ts.tv_sec = (time_t) t;
ts.tv_nsec = (t - ts.tv_sec) * 1e9;
return nanosleep(&ts, NULL) == 0;
}