diff --git a/dpf b/dpf index 1d5a31c..51edc8b 160000 --- a/dpf +++ b/dpf @@ -1 +1 @@ -Subproject commit 1d5a31c1e2fec45b23e05543c646ae6092693914 +Subproject commit 51edc8b6e3c636f29b5fca801bfb2551b0634b91 diff --git a/plugins/common/Semaphore.hpp b/plugins/common/Semaphore.hpp index 10333a6..563a5e6 100644 --- a/plugins/common/Semaphore.hpp +++ b/plugins/common/Semaphore.hpp @@ -1,6 +1,6 @@ /* * DISTRHO Plugin Framework (DPF) - * Copyright (C) 2012-2023 Filipe Coelho + * Copyright (C) 2012-2024 Filipe Coelho * SPDX-License-Identifier: ISC */ @@ -16,6 +16,15 @@ # ifndef NOMINMAX # define NOMINMAX # endif +# ifndef NOKERNEL +# define NOKERNEL +# endif +# ifndef NOSERVICE +# define NOSERVICE +# endif +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif # include # include #else @@ -30,75 +39,117 @@ START_NAMESPACE_DISTRHO class Semaphore { public: - Semaphore(const int initialValue = 0) + Semaphore(const uint16_t initialValue = 0) + #if defined(DISTRHO_OS_MAC) + : task(mach_task_self()), + sem(nullptr) + #elif defined(DISTRHO_OS_WINDOWS) + : handle(INVALID_HANDLE_VALUE) + #else + : sem() + #endif { #if defined(DISTRHO_OS_MAC) - task = mach_task_self(); - DISTRHO_SAFE_ASSERT_RETURN(semaphore_create(task, &sem, SYNC_POLICY_FIFO, initialValue) == KERN_SUCCESS,); + DISTRHO_SAFE_ASSERT_RETURN(semaphore_create(task, + &sem, + SYNC_POLICY_FIFO, + static_cast(initialValue)) == KERN_SUCCESS,); #elif defined(DISTRHO_OS_WINDOWS) - handle = ::CreateSemaphoreA(nullptr, initialValue, std::max(initialValue, 1), nullptr); + handle = CreateSemaphoreA(nullptr, initialValue, LONG_MAX, nullptr); DISTRHO_SAFE_ASSERT_RETURN(handle != INVALID_HANDLE_VALUE,); #else - DISTRHO_SAFE_ASSERT_RETURN(::sem_init(&sem, 0, initialValue) == 0,); + DISTRHO_SAFE_ASSERT_RETURN(sem_init(&sem, 0, initialValue) == 0,); #endif } ~Semaphore() { #if defined(DISTRHO_OS_MAC) - ::semaphore_destroy(task, sem); + semaphore_destroy(task, sem); #elif defined(DISTRHO_OS_WINDOWS) - ::CloseHandle(handle); + CloseHandle(handle); #else - ::sem_destroy(&sem); + sem_destroy(&sem); #endif } void post() { #if defined(DISTRHO_OS_MAC) - ::semaphore_signal(sem); + semaphore_signal(sem); #elif defined(DISTRHO_OS_WINDOWS) - ::ReleaseSemaphore(handle, 1, nullptr); + ReleaseSemaphore(handle, 1, nullptr); #else - ::sem_post(&sem); + sem_post(&sem); #endif } bool wait() { #if defined(DISTRHO_OS_MAC) - return ::semaphore_wait(sem) == KERN_SUCCESS; + return semaphore_wait(sem) == KERN_SUCCESS; #elif defined(DISTRHO_OS_WINDOWS) - return ::WaitForSingleObject(handle, INFINITE) == WAIT_OBJECT_0; + return WaitForSingleObject(handle, INFINITE) == WAIT_OBJECT_0; #else - return ::sem_wait(&sem) == 0; + return sem_wait(&sem) == 0; #endif } - bool timedWait(const uint numSecs) + bool tryWait() { #if defined(DISTRHO_OS_MAC) - const struct mach_timespec time = { numSecs, 0 }; - return ::semaphore_timedwait(sem, time) == KERN_SUCCESS; + const mach_timespec_t zero = { 0, 0 }; + return semaphore_timedwait(sem, zero) == KERN_SUCCESS; #elif defined(DISTRHO_OS_WINDOWS) - return ::WaitForSingleObject(handle, numSecs * 1000) == WAIT_OBJECT_0; + return WaitForSingleObject(handle, 0) == WAIT_OBJECT_0; + #else + return sem_trywait(&sem) == 0; + #endif + } + + bool timedWait(const uint seconds, const uint nanoseconds) + { + #if defined(DISTRHO_OS_MAC) + const mach_timespec_t time = { seconds, static_cast(nanoseconds) }; + return semaphore_timedwait(sem, time) == KERN_SUCCESS; + #elif defined(DISTRHO_OS_WINDOWS) + const uint milliseconds = seconds * 1000U + nanoseconds / 1000000U; + return WaitForSingleObject(handle, milliseconds) == WAIT_OBJECT_0; #else struct timespec timeout; - ::clock_gettime(CLOCK_REALTIME, &timeout); - timeout.tv_sec += numSecs; - return ::sem_timedwait(&sem, &timeout) == 0; + DISTRHO_SAFE_ASSERT_RETURN(clock_gettime(CLOCK_REALTIME, &timeout) == 0, false); + + timeout.tv_sec += seconds; + timeout.tv_nsec += nanoseconds; + if (timeout.tv_nsec >= 1000000000LL) + { + ++timeout.tv_sec; + timeout.tv_nsec -= 1000000000LL; + } + + for (int r;;) + { + r = sem_timedwait(&sem, &timeout); + + if (r < 0) + r = errno; + + if (r == EINTR) + continue; + + return r == 0; + } #endif } private: #if defined(DISTRHO_OS_MAC) - ::mach_port_t task; - ::semaphore_t sem; + mach_port_t task; + semaphore_t sem; #elif defined(DISTRHO_OS_WINDOWS) - ::HANDLE handle; + HANDLE handle; #else - ::sem_t sem; + sem_t sem; #endif };