mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-11-12 21:38:39 +00:00
Convert ticks to 64-bit, added nanosecond precision to the API
Fixes https://github.com/libsdl-org/SDL/issues/5512 Fixes https://github.com/libsdl-org/SDL/issues/6731
This commit is contained in:
@@ -91,7 +91,7 @@ int SDL_CondBroadcast(SDL_cond *cond)
|
||||
return retval;
|
||||
}
|
||||
|
||||
int SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms)
|
||||
int SDL_CondWaitTimeoutNS(SDL_cond *cond, SDL_mutex *mutex, Sint64 timeoutNS)
|
||||
{
|
||||
int retval;
|
||||
#ifndef HAVE_CLOCK_GETTIME
|
||||
@@ -103,18 +103,25 @@ int SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms)
|
||||
return SDL_InvalidParamError("cond");
|
||||
}
|
||||
|
||||
if (timeoutNS < 0) {
|
||||
if (pthread_cond_wait(&cond->cond, &mutex->id) != 0) {
|
||||
return SDL_SetError("pthread_cond_wait() failed");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef HAVE_CLOCK_GETTIME
|
||||
clock_gettime(CLOCK_REALTIME, &abstime);
|
||||
|
||||
abstime.tv_nsec += (ms % 1000) * 1000000;
|
||||
abstime.tv_sec += ms / 1000;
|
||||
abstime.tv_sec += (timeoutNS / SDL_NS_PER_SECOND);
|
||||
abstime.tv_nsec += (timeoutNS % SDL_NS_PER_SECOND);
|
||||
#else
|
||||
gettimeofday(&delta, NULL);
|
||||
|
||||
abstime.tv_sec = delta.tv_sec + (ms / 1000);
|
||||
abstime.tv_nsec = (long)(delta.tv_usec + (ms % 1000) * 1000) * 1000;
|
||||
abstime.tv_sec = delta.tv_sec + (timeoutNS / SDL_NS_PER_SECOND);
|
||||
abstime.tv_nsec = SDL_US_TO_NS(delta.tv_usec) + (timeoutNS % SDL_NS_PER_SECOND);
|
||||
#endif
|
||||
if (abstime.tv_nsec > 1000000000) {
|
||||
while (abstime.tv_nsec > 1000000000) {
|
||||
abstime.tv_sec += 1;
|
||||
abstime.tv_nsec -= 1000000000;
|
||||
}
|
||||
@@ -136,17 +143,4 @@ tryagain:
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Wait on the condition variable, unlocking the provided mutex.
|
||||
The mutex must be locked before entering this function!
|
||||
*/
|
||||
int SDL_CondWait(SDL_cond *cond, SDL_mutex *mutex)
|
||||
{
|
||||
if (cond == NULL) {
|
||||
return SDL_InvalidParamError("cond");
|
||||
} else if (pthread_cond_wait(&cond->cond, &mutex->id) != 0) {
|
||||
return SDL_SetError("pthread_cond_wait() failed");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
@@ -63,39 +63,7 @@ void SDL_DestroySemaphore(SDL_sem *sem)
|
||||
}
|
||||
}
|
||||
|
||||
int SDL_SemTryWait(SDL_sem *sem)
|
||||
{
|
||||
int retval;
|
||||
|
||||
if (sem == NULL) {
|
||||
return SDL_InvalidParamError("sem");
|
||||
}
|
||||
retval = SDL_MUTEX_TIMEDOUT;
|
||||
if (sem_trywait(&sem->sem) == 0) {
|
||||
retval = 0;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
int SDL_SemWait(SDL_sem *sem)
|
||||
{
|
||||
int retval;
|
||||
|
||||
if (sem == NULL) {
|
||||
return SDL_InvalidParamError("sem");
|
||||
}
|
||||
|
||||
do {
|
||||
retval = sem_wait(&sem->sem);
|
||||
} while (retval < 0 && errno == EINTR);
|
||||
|
||||
if (retval < 0) {
|
||||
retval = SDL_SetError("sem_wait() failed");
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
|
||||
int SDL_SemWaitTimeoutNS(SDL_sem *sem, Sint64 timeoutNS)
|
||||
{
|
||||
int retval;
|
||||
#ifdef HAVE_SEM_TIMEDWAIT
|
||||
@@ -104,7 +72,7 @@ int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
|
||||
#endif
|
||||
struct timespec ts_timeout;
|
||||
#else
|
||||
Uint32 end;
|
||||
Uint64 end;
|
||||
#endif
|
||||
|
||||
if (sem == NULL) {
|
||||
@@ -112,11 +80,22 @@ int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
|
||||
}
|
||||
|
||||
/* Try the easy cases first */
|
||||
if (timeout == 0) {
|
||||
return SDL_SemTryWait(sem);
|
||||
if (timeoutNS == 0) {
|
||||
retval = SDL_MUTEX_TIMEDOUT;
|
||||
if (sem_trywait(&sem->sem) == 0) {
|
||||
retval = 0;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
if (timeout == SDL_MUTEX_MAXWAIT) {
|
||||
return SDL_SemWait(sem);
|
||||
if (timeoutNS < 0) {
|
||||
do {
|
||||
retval = sem_wait(&sem->sem);
|
||||
} while (retval < 0 && errno == EINTR);
|
||||
|
||||
if (retval < 0) {
|
||||
retval = SDL_SetError("sem_wait() failed");
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
#ifdef HAVE_SEM_TIMEDWAIT
|
||||
@@ -128,18 +107,18 @@ int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
|
||||
clock_gettime(CLOCK_REALTIME, &ts_timeout);
|
||||
|
||||
/* Add our timeout to current time */
|
||||
ts_timeout.tv_nsec += (timeout % 1000) * 1000000;
|
||||
ts_timeout.tv_sec += timeout / 1000;
|
||||
ts_timeout.tv_sec += (timeoutNS / SDL_NS_PER_SECOND);
|
||||
ts_timeout.tv_nsec += (timeoutNS % SDL_NS_PER_SECOND);
|
||||
#else
|
||||
gettimeofday(&now, NULL);
|
||||
|
||||
/* Add our timeout to current time */
|
||||
ts_timeout.tv_sec = now.tv_sec + (timeout / 1000);
|
||||
ts_timeout.tv_nsec = (now.tv_usec + (timeout % 1000) * 1000) * 1000;
|
||||
ts_timeout.tv_sec = now.tv_sec + (timeoutNS / SDL_NS_PER_SECOND);
|
||||
ts_timeout.tv_nsec = SDL_US_TO_NS(now.tv_usec) + (timeoutNS % SDL_NS_PER_SECOND);
|
||||
#endif
|
||||
|
||||
/* Wrap the second if needed */
|
||||
if (ts_timeout.tv_nsec > 1000000000) {
|
||||
while (ts_timeout.tv_nsec > 1000000000) {
|
||||
ts_timeout.tv_sec += 1;
|
||||
ts_timeout.tv_nsec -= 1000000000;
|
||||
}
|
||||
@@ -157,12 +136,13 @@ int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
|
||||
}
|
||||
}
|
||||
#else
|
||||
end = SDL_GetTicks() + timeout;
|
||||
while ((retval = SDL_SemTryWait(sem)) == SDL_MUTEX_TIMEDOUT) {
|
||||
if (SDL_TICKS_PASSED(SDL_GetTicks(), end)) {
|
||||
end = SDL_GetTicksNS() + timeoutNS;
|
||||
while (sem_trywait(&sem->sem) != 0) {
|
||||
if (SDL_GetTicksNS() >= end) {
|
||||
retval = SDL_MUTEX_TIMEDOUT;
|
||||
break;
|
||||
}
|
||||
SDL_Delay(1);
|
||||
SDL_DelayNS(100);
|
||||
}
|
||||
#endif /* HAVE_SEM_TIMEDWAIT */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user