/* SPDX-License-Identifier: BSL-1.0 OR BSD-3-Clause */ #ifndef MPT_MUTEX_MUTEX_HPP #define MPT_MUTEX_MUTEX_HPP #include "mpt/base/detect.hpp" #include "mpt/base/namespace.hpp" #if !MPT_PLATFORM_MULTITHREADED #define MPT_MUTEX_NONE 1 #elif MPT_COMPILER_GENERIC #define MPT_MUTEX_STD 1 #elif MPT_OS_WINDOWS && MPT_LIBCXX_GNU && !defined(_GLIBCXX_HAS_GTHREADS) && defined(MPT_WITH_MINGWSTDTHREADS) #define MPT_MUTEX_STD 1 #elif MPT_OS_WINDOWS && MPT_LIBCXX_GNU && !defined(_GLIBCXX_HAS_GTHREADS) #define MPT_MUTEX_WIN32 1 #else #define MPT_MUTEX_STD 1 #endif #ifndef MPT_MUTEX_STD #define MPT_MUTEX_STD 0 #endif #ifndef MPT_MUTEX_WIN32 #define MPT_MUTEX_WIN32 0 #endif #ifndef MPT_MUTEX_NONE #define MPT_MUTEX_NONE 0 #endif #if MPT_MUTEX_STD #if !MPT_COMPILER_GENERIC && (defined(__MINGW32__) || defined(__MINGW64__)) && !defined(_GLIBCXX_HAS_GTHREADS) && defined(MPT_WITH_MINGWSTDTHREADS) #include #else #include #ifdef MPT_COMPILER_QUIRK_COMPLEX_STD_MUTEX #include #include #endif #endif #elif MPT_MUTEX_WIN32 #include #endif // MPT_MUTEX namespace mpt { inline namespace MPT_INLINE_NS { #if MPT_MUTEX_STD #ifdef MPT_COMPILER_QUIRK_COMPLEX_STD_MUTEX using mutex = std::conditional::type; #else using mutex = std::mutex; #endif using recursive_mutex = std::recursive_mutex; #elif MPT_MUTEX_WIN32 #if (_WIN32_WINNT >= 0x0600) // _WIN32_WINNT_VISTA // compatible with c++11 std::mutex, can eventually be replaced without touching any usage site class mutex { private: SRWLOCK impl = SRWLOCK_INIT; public: mutex() = default; ~mutex() = default; void lock() { AcquireSRWLockExclusive(&impl); } bool try_lock() { return TryAcquireSRWLockExclusive(&impl) ? true : false; } void unlock() { ReleaseSRWLockExclusive(&impl); } }; #else // !_WIN32_WINNT_VISTA // compatible with c++11 std::mutex, can eventually be replaced without touching any usage site class mutex { private: CRITICAL_SECTION impl; public: mutex() { InitializeCriticalSection(&impl); } ~mutex() { DeleteCriticalSection(&impl); } void lock() { EnterCriticalSection(&impl); } bool try_lock() { return TryEnterCriticalSection(&impl) ? true : false; } void unlock() { LeaveCriticalSection(&impl); } }; #endif // _WIN32_WINNT_VISTA // compatible with c++11 std::recursive_mutex, can eventually be replaced without touching any usage site class recursive_mutex { private: CRITICAL_SECTION impl; public: recursive_mutex() { InitializeCriticalSection(&impl); } ~recursive_mutex() { DeleteCriticalSection(&impl); } void lock() { EnterCriticalSection(&impl); } bool try_lock() { return TryEnterCriticalSection(&impl) ? true : false; } void unlock() { LeaveCriticalSection(&impl); } }; #else // MPT_MUTEX_NONE class mutex { public: mutex() { return; } ~mutex() { return; } void lock() { return; } bool try_lock() { return true; } void unlock() { return; } }; class recursive_mutex { public: recursive_mutex() { return; } ~recursive_mutex() { return; } void lock() { return; } bool try_lock() { return true; } void unlock() { return; } }; #endif // MPT_MUTEX #if MPT_MUTEX_STD template using lock_guard = std::lock_guard; #else // !MPT_MUTEX_STD // compatible with c++11 std::lock_guard, can eventually be replaced without touching any usage site template class lock_guard { private: mutex_type & mutex; public: lock_guard(mutex_type & m) : mutex(m) { mutex.lock(); } ~lock_guard() { mutex.unlock(); } }; #endif // MPT_MUTEX_STD } // namespace MPT_INLINE_NS } // namespace mpt #endif // MPT_MUTEX_MUTEX_HPP