/* Enable IEEE Std 1003.1b-1993 functionality required for clock_gettime. */ #ifdef __linux__ /* Works for Ubuntu 15.10 */ #define _POSIX_C_SOURCE 199309L #elif defined __CYGWIN__ /* Works for Cygwin 2.4.0 64-bit */ #define _POSIX_TIMERS 1 #endif #include "vn/xplat/event.h" #if defined __linux__ || defined __APPLE__ || defined __CYGWIN__ || defined __QNXNTO__ #include #include #endif #ifdef __APPLE__ #include #include #include #include #endif VnError VnEvent_initialize(VnEvent *e) { #ifdef _WIN32 e->handle = CreateEvent( NULL, FALSE, FALSE, NULL); if (e->handle == NULL) return E_UNKNOWN; #elif defined __linux__ || defined __APPLE__ || defined __CYGWIN__ || defined __QNXNTO__ if (pthread_mutex_init(&e->mutex, NULL)) return E_UNKNOWN; if (pthread_cond_init(&e->condition, NULL)) return E_UNKNOWN; e->isTriggered = false; #else #error "Unknown System" #endif return E_NONE; } VnError VnEvent_wait(VnEvent *e) { #ifdef _WIN32 DWORD result; result = WaitForSingleObject(e->handle, 0xffffffff); if (result == WAIT_OBJECT_0) return E_NONE; return E_UNKNOWN; #elif defined __linux__ || defined __APPLE__ || defined __CYGWIN__ || defined __QNXNTO__ if (pthread_mutex_lock(&e->mutex)) return E_UNKNOWN; if (pthread_cond_wait( &e->condition, &e->mutex)) return E_UNKNOWN; if (pthread_mutex_unlock(&e->mutex)) return E_UNKNOWN; return E_NONE; #else #error "Unknown System" #endif } VnError VnEvent_waitMs(VnEvent *e, uint32_t timeoutMs) { #ifdef _WIN32 DWORD result; result = WaitForSingleObject(e->handle, timeoutMs); if (result == WAIT_OBJECT_0) return E_SIGNALED; if (result == WAIT_TIMEOUT) return E_TIMEOUT; return E_UNKNOWN; #elif defined __linux__ || __APPLE__ || __CYGWIN__ || __QNXNTO__ return VnEvent_waitUs(e, timeoutMs * 1000); #else #error "Unknown System" #endif } VnError VnEvent_waitUs(VnEvent *e, uint32_t timeoutUs) { #ifdef _WIN32 DWORD result; result = WaitForSingleObject( e->handle, timeoutUs / 1000); if (result == WAIT_OBJECT_0) return E_SIGNALED; if (result == WAIT_TIMEOUT) return E_TIMEOUT; #elif (defined __linux__ || defined __CYGWIN__ || defined __QNXNTO__) struct timespec now; int errorCode; uint32_t numOfSecs, numOfNanoseconds; if (pthread_mutex_lock(&e->mutex)) return E_UNKNOWN; if (clock_gettime(CLOCK_REALTIME, &now)) return E_UNKNOWN; numOfSecs = timeoutUs / 1000000; numOfNanoseconds = (timeoutUs % 1000000) * 1000; now.tv_sec += numOfSecs; now.tv_nsec += numOfNanoseconds; if (now.tv_nsec > 1000000000) { now.tv_nsec %= 1000000000; now.tv_sec++; } errorCode = pthread_cond_timedwait( &e->condition, &e->mutex, &now); if (pthread_mutex_unlock(&e->mutex)) return E_UNKNOWN; if (!errorCode) return E_SIGNALED; if (errorCode == ETIMEDOUT) return E_TIMEOUT; #elif defined __APPLE__ pthread_mutex_lock(&e->mutex); clock_serv_t cclock; mach_struct timespec_t mts; host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock); clock_get_time(cclock, &mts); mach_port_deallocate(mach_task_self(), cclock); struct timespec now; now.tv_sec = mts.tv_sec; now.tv_nsec = mts.tv_nsec; uint32_t numOfSecs = timeoutUs / 1000000; uint32_t numOfNanoseconds = (timeoutUs % 1000000) * 1000; now.tv_sec += numOfSecs; now.tv_nsec += numOfNanoseconds; if (now.tv_nsec > 1000000000) { now.tv_nsec %= 1000000000; now.tv_sec++; } int errorCode = pthread_cond_timedwait( &e->condition, &e->mutex, &now); pthread_mutex_unlock(&e->mutex); if (errorCode == 0) return E_SIGNALED; if (errorCode == ETIMEDOUT) return E_TIMEOUT; #else #error "Unknown System" #endif return E_UNKNOWN; } VnError VnEvent_signal(VnEvent *e) { #ifdef _WIN32 if (!SetEvent(e->handle)) return E_UNKNOWN; #elif defined __linux__ || __APPLE__ || __CYGWIN__ || __QNXNTO__ if (pthread_mutex_lock(&e->mutex)) return E_UNKNOWN; e->isTriggered = true; if (pthread_cond_signal(&e->condition)) return E_UNKNOWN; if (pthread_mutex_unlock(&e->mutex)) return E_UNKNOWN; #else #error "Unknown System" #endif return E_NONE; }