// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics) // SPDX-FileCopyrightText: 2023 Jorrit Rouwe // SPDX-License-Identifier: MIT #pragma once #include // Determine which platform specific construct we'll use JPH_SUPPRESS_WARNINGS_STD_BEGIN #ifdef JPH_PLATFORM_WINDOWS // We include windows.h in the cpp file, the semaphore itself is a void pointer #elif defined(JPH_PLATFORM_LINUX) || defined(JPH_PLATFORM_ANDROID) || defined(JPH_PLATFORM_BSD) || defined(JPH_PLATFORM_WASM) #include #define JPH_USE_PTHREADS #elif defined(JPH_PLATFORM_MACOS) || defined(JPH_PLATFORM_IOS) #include #define JPH_USE_GRAND_CENTRAL_DISPATCH #elif defined(JPH_PLATFORM_BLUE) // Jolt/Core/PlatformBlue.h should have defined everything that is needed below #else #include #include #endif JPH_SUPPRESS_WARNINGS_STD_END JPH_NAMESPACE_BEGIN /// Implements a semaphore /// When we switch to C++20 we can use counting_semaphore to unify this class JPH_EXPORT Semaphore { public: /// Constructor Semaphore(); ~Semaphore(); /// Release the semaphore, signaling the thread waiting on the barrier that there may be work void Release(uint inNumber = 1); /// Acquire the semaphore inNumber times void Acquire(uint inNumber = 1); /// Get the current value of the semaphore inline int GetValue() const { return mCount.load(std::memory_order_relaxed); } private: #if defined(JPH_PLATFORM_WINDOWS) || defined(JPH_USE_PTHREADS) || defined(JPH_USE_GRAND_CENTRAL_DISPATCH) || defined(JPH_PLATFORM_BLUE) #ifdef JPH_PLATFORM_WINDOWS using SemaphoreType = void *; #elif defined(JPH_USE_PTHREADS) using SemaphoreType = sem_t; #elif defined(JPH_USE_GRAND_CENTRAL_DISPATCH) using SemaphoreType = dispatch_semaphore_t; #elif defined(JPH_PLATFORM_BLUE) using SemaphoreType = JPH_PLATFORM_BLUE_SEMAPHORE; #endif alignas(JPH_CACHE_LINE_SIZE) atomic mCount { 0 }; ///< We increment mCount for every release, to acquire we decrement the count. If the count is negative we know that we are waiting on the actual semaphore. SemaphoreType mSemaphore { }; ///< The semaphore is an expensive construct so we only acquire/release it if we know that we need to wait/have waiting threads #else // Other platforms: Emulate a semaphore using a mutex, condition variable and count std::mutex mLock; std::condition_variable mWaitVariable; atomic mCount { 0 }; #endif }; JPH_NAMESPACE_END