| @@ -21,15 +21,19 @@ | |||
| #include "CarlaUtils.hpp" | |||
| #include <ctime> | |||
| #include <sys/time.h> | |||
| #include <sys/types.h> | |||
| #include <semaphore.h> | |||
| #if defined(CARLA_OS_MAC) | |||
| # include <fcntl.h> | |||
| #ifdef CARLA_OS_WIN | |||
| struct sem_t { HANDLE handle; }; | |||
| #else | |||
| # include <sys/time.h> | |||
| # include <sys/types.h> | |||
| # include <semaphore.h> | |||
| # ifdef CARLA_OS_MAC | |||
| # include <fcntl.h> | |||
| extern "C" { | |||
| # include "osx_sem_timedwait.c" | |||
| # include "osx_sem_timedwait.c" | |||
| }; | |||
| # endif | |||
| #endif | |||
| /* | |||
| @@ -38,7 +42,19 @@ extern "C" { | |||
| static inline | |||
| sem_t* carla_sem_create() noexcept | |||
| { | |||
| #if defined(CARLA_OS_MAC) | |||
| #if defined(CARLA_OS_WIN) | |||
| sem_t* const sem = (sem_t*)std::malloc(sizeof(sem_t)); | |||
| CARLA_SAFE_ASSERT_RETURN(sem != nullptr, nullptr); | |||
| SECURITY_ATTRIBUTES sa; | |||
| carla_zeroStruct(sa); | |||
| sa.nLength = sizeof(SECURITY_ATTRIBUTES); | |||
| sa.bInheritHandle = TRUE; | |||
| sem->handle = ::CreateSemaphore(&sa, 0, 1, nullptr); | |||
| return sem; | |||
| #elif defined(CARLA_OS_MAC) | |||
| static ulong sCounter = 0; | |||
| ++sCounter; | |||
| @@ -77,7 +93,10 @@ void carla_sem_destroy(sem_t* const sem) noexcept | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(sem != nullptr,); | |||
| #if defined(CARLA_OS_MAC) | |||
| #if defined(CARLA_OS_WIN) | |||
| ::CloseHandle(sem->handle); | |||
| std::free(sem); | |||
| #elif defined(CARLA_OS_MAC) | |||
| ::sem_close(sem); | |||
| #else | |||
| // we can't call "sem_destroy(sem)" directly because it will free memory which we allocated during carla_sem_create() | |||
| @@ -87,12 +106,12 @@ void carla_sem_destroy(sem_t* const sem) noexcept | |||
| sem_t sem2; | |||
| std::memcpy(&sem2, sem, sizeof(sem_t)); | |||
| // destroy semaphore | |||
| ::sem_destroy(&sem2); | |||
| // free memory allocated in carla_sem_create() | |||
| // FIXME | |||
| //std::free(sem); | |||
| // destroy semaphore | |||
| ::sem_destroy(&sem2); | |||
| #endif | |||
| } | |||
| @@ -104,7 +123,11 @@ bool carla_sem_post(sem_t* const sem) noexcept | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(sem != nullptr, false); | |||
| #ifdef CARLA_OS_WIN | |||
| return (::ReleaseSemaphore(sem->handle, 1, nullptr) != FALSE); | |||
| #else | |||
| return (::sem_post(sem) == 0); | |||
| #endif | |||
| } | |||
| /* | |||
| @@ -116,20 +139,36 @@ bool carla_sem_timedwait(sem_t* const sem, const uint secs) noexcept | |||
| CARLA_SAFE_ASSERT_RETURN(sem != nullptr, false); | |||
| CARLA_SAFE_ASSERT_RETURN(secs > 0, false); | |||
| #if defined(CARLA_OS_WIN) | |||
| const DWORD result = ::WaitForSingleObject(sem->handle, secs*1000); | |||
| switch (result) | |||
| { | |||
| case WAIT_OBJECT_0: | |||
| return true; | |||
| case WAIT_TIMEOUT: | |||
| errno = ETIMEDOUT; | |||
| return false; | |||
| default: | |||
| errno = EINTR; | |||
| return false; | |||
| } | |||
| #else | |||
| timespec timeout; | |||
| #ifdef CARLA_OS_LINUX | |||
| # ifdef CARLA_OS_LINUX | |||
| ::clock_gettime(CLOCK_REALTIME, &timeout); | |||
| #else | |||
| # else | |||
| timeval now; | |||
| ::gettimeofday(&now, nullptr); | |||
| timeout.tv_sec = now.tv_sec; | |||
| timeout.tv_nsec = now.tv_usec * 1000; | |||
| #endif | |||
| # endif | |||
| timeout.tv_sec += static_cast<time_t>(secs); | |||
| try { | |||
| return (::sem_timedwait(sem, &timeout) == 0); | |||
| } CARLA_SAFE_EXCEPTION_RETURN("sem_timedwait", false); | |||
| #endif | |||
| } | |||
| // ----------------------------------------------------------------------- | |||