diff --git a/include/SDL_mutex.h b/include/SDL_mutex.h index 562c3b06f..7ef294e1a 100644 --- a/include/SDL_mutex.h +++ b/include/SDL_mutex.h @@ -73,6 +73,13 @@ extern DECLSPEC SDL_mutex *SDLCALL SDL_CreateMutex(void); #define SDL_LockMutex(m) SDL_mutexP(m) extern DECLSPEC int SDLCALL SDL_mutexP(SDL_mutex * mutex); +/** + * Try to lock the mutex + * + * \return 0, SDL_MUTEX_TIMEDOUT, or -1 on error + */ +extern DECLSPEC int SDLCALL SDL_TryLockMutex(SDL_mutex * mutex); + /** * Unlock the mutex. * diff --git a/src/thread/generic/SDL_sysmutex.c b/src/thread/generic/SDL_sysmutex.c index a68f238c7..6cc32ec70 100644 --- a/src/thread/generic/SDL_sysmutex.c +++ b/src/thread/generic/SDL_sysmutex.c @@ -68,7 +68,7 @@ SDL_DestroyMutex(SDL_mutex * mutex) } } -/* Lock the semaphore */ +/* Lock the mutex */ int SDL_mutexP(SDL_mutex * mutex) { @@ -99,6 +99,40 @@ SDL_mutexP(SDL_mutex * mutex) #endif /* SDL_THREADS_DISABLED */ } +/* try Lock the mutex */ +int +SDL_TryLockMutex(SDL_mutex * mutex) +{ +#if SDL_THREADS_DISABLED + return 0; +#else + int retval = 0; + SDL_threadID this_thread; + + if (mutex == NULL) { + SDL_SetError("Passed a NULL mutex"); + return -1; + } + + this_thread = SDL_ThreadID(); + if (mutex->owner == this_thread) { + ++mutex->recursive; + } else { + /* The order of operations is important. + We set the locking thread id after we obtain the lock + so unlocks from other threads will fail. + */ + retval = SDL_SemWait(mutex->sem); + if (retval == 0) { + mutex->owner = this_thread; + mutex->recursive = 0; + } + } + + return retval; +#endif /* SDL_THREADS_DISABLED */ +} + /* Unlock the mutex */ int SDL_mutexV(SDL_mutex * mutex) diff --git a/src/thread/nds/SDL_sysmutex.c b/src/thread/nds/SDL_sysmutex.c index 6b662c99f..ec940dd24 100644 --- a/src/thread/nds/SDL_sysmutex.c +++ b/src/thread/nds/SDL_sysmutex.c @@ -76,7 +76,7 @@ SDL_DestroyMutex(SDL_mutex * mutex) } } -/* Lock the semaphore */ +/* Lock the mutex */ int SDL_mutexP(SDL_mutex * mutex) { @@ -107,6 +107,40 @@ SDL_mutexP(SDL_mutex * mutex) #endif /* DISABLE_THREADS */ } +/* Try Lock the mutex */ +int +SDL_TryLockMutex(SDL_mutex * mutex) +{ +#ifdef DISABLE_THREADS + return 0; +#else + int retval = 0; + SDL_threadID this_thread; + + if (mutex == NULL) { + SDL_SetError("Passed a NULL mutex"); + return -1; + } + + this_thread = SDL_ThreadID(); + if (mutex->owner == this_thread) { + ++mutex->recursive; + } else { + /* The order of operations is important. + We set the locking thread id after we obtain the lock + so unlocks from other threads will fail. + */ + retval = SDL_SemTryWait(mutex->sem); + if (ret == 0) { + mutex->owner = this_thread; + mutex->recursive = 0; + } + } + + return retval; +#endif /* DISABLE_THREADS */ +} + /* Unlock the mutex */ int SDL_mutexV(SDL_mutex * mutex) diff --git a/src/thread/pthread/SDL_sysmutex.c b/src/thread/pthread/SDL_sysmutex.c index ce611c082..6d1a1d92e 100644 --- a/src/thread/pthread/SDL_sysmutex.c +++ b/src/thread/pthread/SDL_sysmutex.c @@ -22,6 +22,7 @@ #define _GNU_SOURCE #include +#include #include "SDL_thread.h" @@ -117,6 +118,52 @@ SDL_mutexP(SDL_mutex * mutex) return retval; } +int +SDL_TryLockMutex(SDL_mutex * mutex) +{ + int retval; +#if FAKE_RECURSIVE_MUTEX + pthread_t this_thread; +#endif + + if (mutex == NULL) { + SDL_SetError("Passed a NULL mutex"); + return -1; + } + + retval = 0; +#if FAKE_RECURSIVE_MUTEX + this_thread = pthread_self(); + if (mutex->owner == this_thead) { + ++mutex->recursive; + } else { + /* The order of operations is important. + We set the locking thread id after we obtain the lock + so unlocks from other threads will fail. + */ + if (pthread_mutex_lock(&mutex->id) == 0) { + mutex->owner = this_thread; + mutex->recursive = 0; + } else if (errno == EBUSY) { + retval = SDL_MUTEX_TIMEDOUT; + } else { + SDL_SetError("pthread_mutex_trylock() failed"); + retval = -1; + } + } +#else + if (pthread_mutex_trylock(&mutex->id) != 0) { + if (errno == EBUSY) { + retval = SDL_MUTEX_TIMEDOUT; + } else { + SDL_SetError("pthread_mutex_trylock() failed"); + retval = -1; + } + } +#endif + return retval; +} + int SDL_mutexV(SDL_mutex * mutex) { diff --git a/src/thread/windows/SDL_sysmutex.c b/src/thread/windows/SDL_sysmutex.c index 7d88c79a2..02883dcc4 100644 --- a/src/thread/windows/SDL_sysmutex.c +++ b/src/thread/windows/SDL_sysmutex.c @@ -75,6 +75,22 @@ SDL_mutexP(SDL_mutex * mutex) return (0); } +/* TryLock the mutex */ +int +SDL_TryLockMutex(SDL_mutex * mutex) +{ + if (mutex == NULL) { + SDL_SetError("Passed a NULL mutex"); + return -1; + } + + int retval = 0; + if (TryEnterCriticalSection(&mutex->cs) == 0) { + retval = SDL_MUTEX_TIMEDOUT; + } + return retval; +} + /* Unlock the mutex */ int SDL_mutexV(SDL_mutex * mutex)