|
|
- /*
- Simple DirectMedia Layer
- Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
-
- This software is provided 'as-is', without any express or implied
- warranty. In no event will the authors be held liable for any damages
- arising from the use of this software.
-
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it
- freely, subject to the following restrictions:
-
- 1. The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
-
- #ifndef SDL_mutex_h_
- #define SDL_mutex_h_
-
- /**
- * \file SDL_mutex.h
- *
- * Functions to provide thread synchronization primitives.
- */
-
- #include "SDL_stdinc.h"
- #include "SDL_error.h"
-
- /******************************************************************************/
- /* Enable thread safety attributes only with clang.
- * The attributes can be safely erased when compiling with other compilers.
- */
- #if defined(SDL_THREAD_SAFETY_ANALYSIS) && \
- defined(__clang__) && (!defined(SWIG))
- #define SDL_THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
- #else
- #define SDL_THREAD_ANNOTATION_ATTRIBUTE__(x) /* no-op */
- #endif
-
- #define SDL_CAPABILITY(x) \
- SDL_THREAD_ANNOTATION_ATTRIBUTE__(capability(x))
-
- #define SDL_SCOPED_CAPABILITY \
- SDL_THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)
-
- #define SDL_GUARDED_BY(x) \
- SDL_THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x))
-
- #define SDL_PT_GUARDED_BY(x) \
- SDL_THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x))
-
- #define SDL_ACQUIRED_BEFORE(x) \
- SDL_THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(x))
-
- #define SDL_ACQUIRED_AFTER(x) \
- SDL_THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(x))
-
- #define SDL_REQUIRES(x) \
- SDL_THREAD_ANNOTATION_ATTRIBUTE__(requires_capability(x))
-
- #define SDL_REQUIRES_SHARED(x) \
- SDL_THREAD_ANNOTATION_ATTRIBUTE__(requires_shared_capability(x))
-
- #define SDL_ACQUIRE(x) \
- SDL_THREAD_ANNOTATION_ATTRIBUTE__(acquire_capability(x))
-
- #define SDL_ACQUIRE_SHARED(x) \
- SDL_THREAD_ANNOTATION_ATTRIBUTE__(acquire_shared_capability(x))
-
- #define SDL_RELEASE(x) \
- SDL_THREAD_ANNOTATION_ATTRIBUTE__(release_capability(x))
-
- #define SDL_RELEASE_SHARED(x) \
- SDL_THREAD_ANNOTATION_ATTRIBUTE__(release_shared_capability(x))
-
- #define SDL_RELEASE_GENERIC(x) \
- SDL_THREAD_ANNOTATION_ATTRIBUTE__(release_generic_capability(x))
-
- #define SDL_TRY_ACQUIRE(x, y) \
- SDL_THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_capability(x, y))
-
- #define SDL_TRY_ACQUIRE_SHARED(x, y) \
- SDL_THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_shared_capability(x, y))
-
- #define SDL_EXCLUDES(x) \
- SDL_THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(x))
-
- #define SDL_ASSERT_CAPABILITY(x) \
- SDL_THREAD_ANNOTATION_ATTRIBUTE__(assert_capability(x))
-
- #define SDL_ASSERT_SHARED_CAPABILITY(x) \
- SDL_THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_capability(x))
-
- #define SDL_RETURN_CAPABILITY(x) \
- SDL_THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x))
-
- #define SDL_NO_THREAD_SAFETY_ANALYSIS \
- SDL_THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis)
-
- /******************************************************************************/
-
-
- #include "begin_code.h"
- /* Set up for C function definitions, even when using C++ */
- #ifdef __cplusplus
- extern "C" {
- #endif
-
- /**
- * Synchronization functions which can time out return this value
- * if they time out.
- */
- #define SDL_MUTEX_TIMEDOUT 1
-
- /**
- * This is the timeout value which corresponds to never time out.
- */
- #define SDL_MUTEX_MAXWAIT (~(Uint32)0)
-
-
- /**
- * \name Mutex functions
- */
- /* @{ */
-
- /* The SDL mutex structure, defined in SDL_sysmutex.c */
- struct SDL_mutex;
- typedef struct SDL_mutex SDL_mutex;
-
- /**
- * Create a new mutex.
- *
- * All newly-created mutexes begin in the _unlocked_ state.
- *
- * Calls to SDL_LockMutex() will not return while the mutex is locked by
- * another thread. See SDL_TryLockMutex() to attempt to lock without blocking.
- *
- * SDL mutexes are reentrant.
- *
- * \returns the initialized and unlocked mutex or NULL on failure; call
- * SDL_GetError() for more information.
- *
- * \since This function is available since SDL 2.0.0.
- *
- * \sa SDL_DestroyMutex
- * \sa SDL_LockMutex
- * \sa SDL_TryLockMutex
- * \sa SDL_UnlockMutex
- */
- extern DECLSPEC SDL_mutex *SDLCALL SDL_CreateMutex(void);
-
- /**
- * Lock the mutex.
- *
- * This will block until the mutex is available, which is to say it is in the
- * unlocked state and the OS has chosen the caller as the next thread to lock
- * it. Of all threads waiting to lock the mutex, only one may do so at a time.
- *
- * It is legal for the owning thread to lock an already-locked mutex. It must
- * unlock it the same number of times before it is actually made available for
- * other threads in the system (this is known as a "recursive mutex").
- *
- * \param mutex the mutex to lock
- * \return 0, or -1 on error.
- *
- * \since This function is available since SDL 2.0.0.
- */
- extern DECLSPEC int SDLCALL SDL_LockMutex(SDL_mutex * mutex) SDL_ACQUIRE(mutex);
- #define SDL_mutexP(m) SDL_LockMutex(m)
-
- /**
- * Try to lock a mutex without blocking.
- *
- * This works just like SDL_LockMutex(), but if the mutex is not available,
- * this function returns `SDL_MUTEX_TIMEOUT` immediately.
- *
- * This technique is useful if you need exclusive access to a resource but
- * don't want to wait for it, and will return to it to try again later.
- *
- * \param mutex the mutex to try to lock
- * \returns 0, `SDL_MUTEX_TIMEDOUT`, or -1 on error; call SDL_GetError() for
- * more information.
- *
- * \since This function is available since SDL 2.0.0.
- *
- * \sa SDL_CreateMutex
- * \sa SDL_DestroyMutex
- * \sa SDL_LockMutex
- * \sa SDL_UnlockMutex
- */
- extern DECLSPEC int SDLCALL SDL_TryLockMutex(SDL_mutex * mutex) SDL_TRY_ACQUIRE(0, mutex);
-
- /**
- * Unlock the mutex.
- *
- * It is legal for the owning thread to lock an already-locked mutex. It must
- * unlock it the same number of times before it is actually made available for
- * other threads in the system (this is known as a "recursive mutex").
- *
- * It is an error to unlock a mutex that has not been locked by the current
- * thread, and doing so results in undefined behavior.
- *
- * It is also an error to unlock a mutex that isn't locked at all.
- *
- * \param mutex the mutex to unlock.
- * \returns 0, or -1 on error.
- *
- * \since This function is available since SDL 2.0.0.
- */
- extern DECLSPEC int SDLCALL SDL_UnlockMutex(SDL_mutex * mutex) SDL_RELEASE(mutex);
- #define SDL_mutexV(m) SDL_UnlockMutex(m)
-
- /**
- * Destroy a mutex created with SDL_CreateMutex().
- *
- * This function must be called on any mutex that is no longer needed. Failure
- * to destroy a mutex will result in a system memory or resource leak. While
- * it is safe to destroy a mutex that is _unlocked_, it is not safe to attempt
- * to destroy a locked mutex, and may result in undefined behavior depending
- * on the platform.
- *
- * \param mutex the mutex to destroy
- *
- * \since This function is available since SDL 2.0.0.
- *
- * \sa SDL_CreateMutex
- * \sa SDL_LockMutex
- * \sa SDL_TryLockMutex
- * \sa SDL_UnlockMutex
- */
- extern DECLSPEC void SDLCALL SDL_DestroyMutex(SDL_mutex * mutex);
-
- /* @} *//* Mutex functions */
-
-
- /**
- * \name Semaphore functions
- */
- /* @{ */
-
- /* The SDL semaphore structure, defined in SDL_syssem.c */
- struct SDL_semaphore;
- typedef struct SDL_semaphore SDL_sem;
-
- /**
- * Create a semaphore.
- *
- * This function creates a new semaphore and initializes it with the value
- * `initial_value`. Each wait operation on the semaphore will atomically
- * decrement the semaphore value and potentially block if the semaphore value
- * is 0. Each post operation will atomically increment the semaphore value and
- * wake waiting threads and allow them to retry the wait operation.
- *
- * \param initial_value the starting value of the semaphore
- * \returns a new semaphore or NULL on failure; call SDL_GetError() for more
- * information.
- *
- * \since This function is available since SDL 2.0.0.
- *
- * \sa SDL_DestroySemaphore
- * \sa SDL_SemPost
- * \sa SDL_SemTryWait
- * \sa SDL_SemValue
- * \sa SDL_SemWait
- * \sa SDL_SemWaitTimeout
- */
- extern DECLSPEC SDL_sem *SDLCALL SDL_CreateSemaphore(Uint32 initial_value);
-
- /**
- * Destroy a semaphore.
- *
- * It is not safe to destroy a semaphore if there are threads currently
- * waiting on it.
- *
- * \param sem the semaphore to destroy
- *
- * \since This function is available since SDL 2.0.0.
- *
- * \sa SDL_CreateSemaphore
- * \sa SDL_SemPost
- * \sa SDL_SemTryWait
- * \sa SDL_SemValue
- * \sa SDL_SemWait
- * \sa SDL_SemWaitTimeout
- */
- extern DECLSPEC void SDLCALL SDL_DestroySemaphore(SDL_sem * sem);
-
- /**
- * Wait until a semaphore has a positive value and then decrements it.
- *
- * This function suspends the calling thread until either the semaphore
- * pointed to by `sem` has a positive value or the call is interrupted by a
- * signal or error. If the call is successful it will atomically decrement the
- * semaphore value.
- *
- * This function is the equivalent of calling SDL_SemWaitTimeout() with a time
- * length of `SDL_MUTEX_MAXWAIT`.
- *
- * \param sem the semaphore wait on
- * \returns 0 on success or a negative error code on failure; call
- * SDL_GetError() for more information.
- *
- * \since This function is available since SDL 2.0.0.
- *
- * \sa SDL_CreateSemaphore
- * \sa SDL_DestroySemaphore
- * \sa SDL_SemPost
- * \sa SDL_SemTryWait
- * \sa SDL_SemValue
- * \sa SDL_SemWait
- * \sa SDL_SemWaitTimeout
- */
- extern DECLSPEC int SDLCALL SDL_SemWait(SDL_sem * sem);
-
- /**
- * See if a semaphore has a positive value and decrement it if it does.
- *
- * This function checks to see if the semaphore pointed to by `sem` has a
- * positive value and atomically decrements the semaphore value if it does. If
- * the semaphore doesn't have a positive value, the function immediately
- * returns SDL_MUTEX_TIMEDOUT.
- *
- * \param sem the semaphore to wait on
- * \returns 0 if the wait succeeds, `SDL_MUTEX_TIMEDOUT` if the wait would
- * block, or a negative error code on failure; call SDL_GetError()
- * for more information.
- *
- * \since This function is available since SDL 2.0.0.
- *
- * \sa SDL_CreateSemaphore
- * \sa SDL_DestroySemaphore
- * \sa SDL_SemPost
- * \sa SDL_SemValue
- * \sa SDL_SemWait
- * \sa SDL_SemWaitTimeout
- */
- extern DECLSPEC int SDLCALL SDL_SemTryWait(SDL_sem * sem);
-
- /**
- * Wait until a semaphore has a positive value and then decrements it.
- *
- * This function suspends the calling thread until either the semaphore
- * pointed to by `sem` has a positive value, the call is interrupted by a
- * signal or error, or the specified time has elapsed. If the call is
- * successful it will atomically decrement the semaphore value.
- *
- * \param sem the semaphore to wait on
- * \param timeout the length of the timeout, in milliseconds
- * \returns 0 if the wait succeeds, `SDL_MUTEX_TIMEDOUT` if the wait does not
- * succeed in the allotted time, or a negative error code on failure;
- * call SDL_GetError() for more information.
- *
- * \since This function is available since SDL 2.0.0.
- *
- * \sa SDL_CreateSemaphore
- * \sa SDL_DestroySemaphore
- * \sa SDL_SemPost
- * \sa SDL_SemTryWait
- * \sa SDL_SemValue
- * \sa SDL_SemWait
- */
- extern DECLSPEC int SDLCALL SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout);
-
- /**
- * Atomically increment a semaphore's value and wake waiting threads.
- *
- * \param sem the semaphore to increment
- * \returns 0 on success or a negative error code on failure; call
- * SDL_GetError() for more information.
- *
- * \since This function is available since SDL 2.0.0.
- *
- * \sa SDL_CreateSemaphore
- * \sa SDL_DestroySemaphore
- * \sa SDL_SemTryWait
- * \sa SDL_SemValue
- * \sa SDL_SemWait
- * \sa SDL_SemWaitTimeout
- */
- extern DECLSPEC int SDLCALL SDL_SemPost(SDL_sem * sem);
-
- /**
- * Get the current value of a semaphore.
- *
- * \param sem the semaphore to query
- * \returns the current value of the semaphore.
- *
- * \since This function is available since SDL 2.0.0.
- *
- * \sa SDL_CreateSemaphore
- */
- extern DECLSPEC Uint32 SDLCALL SDL_SemValue(SDL_sem * sem);
-
- /* @} *//* Semaphore functions */
-
-
- /**
- * \name Condition variable functions
- */
- /* @{ */
-
- /* The SDL condition variable structure, defined in SDL_syscond.c */
- struct SDL_cond;
- typedef struct SDL_cond SDL_cond;
-
- /**
- * Create a condition variable.
- *
- * \returns a new condition variable or NULL on failure; call SDL_GetError()
- * for more information.
- *
- * \since This function is available since SDL 2.0.0.
- *
- * \sa SDL_CondBroadcast
- * \sa SDL_CondSignal
- * \sa SDL_CondWait
- * \sa SDL_CondWaitTimeout
- * \sa SDL_DestroyCond
- */
- extern DECLSPEC SDL_cond *SDLCALL SDL_CreateCond(void);
-
- /**
- * Destroy a condition variable.
- *
- * \param cond the condition variable to destroy
- *
- * \since This function is available since SDL 2.0.0.
- *
- * \sa SDL_CondBroadcast
- * \sa SDL_CondSignal
- * \sa SDL_CondWait
- * \sa SDL_CondWaitTimeout
- * \sa SDL_CreateCond
- */
- extern DECLSPEC void SDLCALL SDL_DestroyCond(SDL_cond * cond);
-
- /**
- * Restart one of the threads that are waiting on the condition variable.
- *
- * \param cond the condition variable to signal
- * \returns 0 on success or a negative error code on failure; call
- * SDL_GetError() for more information.
- *
- * \since This function is available since SDL 2.0.0.
- *
- * \sa SDL_CondBroadcast
- * \sa SDL_CondWait
- * \sa SDL_CondWaitTimeout
- * \sa SDL_CreateCond
- * \sa SDL_DestroyCond
- */
- extern DECLSPEC int SDLCALL SDL_CondSignal(SDL_cond * cond);
-
- /**
- * Restart all threads that are waiting on the condition variable.
- *
- * \param cond the condition variable to signal
- * \returns 0 on success or a negative error code on failure; call
- * SDL_GetError() for more information.
- *
- * \since This function is available since SDL 2.0.0.
- *
- * \sa SDL_CondSignal
- * \sa SDL_CondWait
- * \sa SDL_CondWaitTimeout
- * \sa SDL_CreateCond
- * \sa SDL_DestroyCond
- */
- extern DECLSPEC int SDLCALL SDL_CondBroadcast(SDL_cond * cond);
-
- /**
- * Wait until a condition variable is signaled.
- *
- * This function unlocks the specified `mutex` and waits for another thread to
- * call SDL_CondSignal() or SDL_CondBroadcast() on the condition variable
- * `cond`. Once the condition variable is signaled, the mutex is re-locked and
- * the function returns.
- *
- * The mutex must be locked before calling this function.
- *
- * This function is the equivalent of calling SDL_CondWaitTimeout() with a
- * time length of `SDL_MUTEX_MAXWAIT`.
- *
- * \param cond the condition variable to wait on
- * \param mutex the mutex used to coordinate thread access
- * \returns 0 when it is signaled or a negative error code on failure; call
- * SDL_GetError() for more information.
- *
- * \since This function is available since SDL 2.0.0.
- *
- * \sa SDL_CondBroadcast
- * \sa SDL_CondSignal
- * \sa SDL_CondWaitTimeout
- * \sa SDL_CreateCond
- * \sa SDL_DestroyCond
- */
- extern DECLSPEC int SDLCALL SDL_CondWait(SDL_cond * cond, SDL_mutex * mutex);
-
- /**
- * Wait until a condition variable is signaled or a certain time has passed.
- *
- * This function unlocks the specified `mutex` and waits for another thread to
- * call SDL_CondSignal() or SDL_CondBroadcast() on the condition variable
- * `cond`, or for the specified time to elapse. Once the condition variable is
- * signaled or the time elapsed, the mutex is re-locked and the function
- * returns.
- *
- * The mutex must be locked before calling this function.
- *
- * \param cond the condition variable to wait on
- * \param mutex the mutex used to coordinate thread access
- * \param ms the maximum time to wait, in milliseconds, or `SDL_MUTEX_MAXWAIT`
- * to wait indefinitely
- * \returns 0 if the condition variable is signaled, `SDL_MUTEX_TIMEDOUT` if
- * the condition is not signaled in the allotted time, or a negative
- * error code on failure; call SDL_GetError() for more information.
- *
- * \since This function is available since SDL 2.0.0.
- *
- * \sa SDL_CondBroadcast
- * \sa SDL_CondSignal
- * \sa SDL_CondWait
- * \sa SDL_CreateCond
- * \sa SDL_DestroyCond
- */
- extern DECLSPEC int SDLCALL SDL_CondWaitTimeout(SDL_cond * cond,
- SDL_mutex * mutex, Uint32 ms);
-
- /* @} *//* Condition variable functions */
-
-
- /* Ends C function definitions when using C++ */
- #ifdef __cplusplus
- }
- #endif
- #include "close_code.h"
-
- #endif /* SDL_mutex_h_ */
-
- /* vi: set ts=4 sw=4 expandtab: */
|