Semaphore.h 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. // Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
  2. // SPDX-FileCopyrightText: 2023 Jorrit Rouwe
  3. // SPDX-License-Identifier: MIT
  4. #pragma once
  5. #include <Jolt/Core/Atomics.h>
  6. // Determine which platform specific construct we'll use
  7. JPH_SUPPRESS_WARNINGS_STD_BEGIN
  8. #ifdef JPH_PLATFORM_WINDOWS
  9. // We include windows.h in the cpp file, the semaphore itself is a void pointer
  10. #elif defined(JPH_PLATFORM_LINUX) || defined(JPH_PLATFORM_ANDROID) || defined(JPH_PLATFORM_BSD) || defined(JPH_PLATFORM_WASM)
  11. #include <semaphore.h>
  12. #define JPH_USE_PTHREADS
  13. #elif defined(JPH_PLATFORM_MACOS) || defined(JPH_PLATFORM_IOS)
  14. #include <dispatch/dispatch.h>
  15. #define JPH_USE_GRAND_CENTRAL_DISPATCH
  16. #elif defined(JPH_PLATFORM_BLUE)
  17. // Jolt/Core/PlatformBlue.h should have defined everything that is needed below
  18. #else
  19. #include <mutex>
  20. #include <condition_variable>
  21. #endif
  22. JPH_SUPPRESS_WARNINGS_STD_END
  23. JPH_NAMESPACE_BEGIN
  24. /// Implements a semaphore
  25. /// When we switch to C++20 we can use counting_semaphore to unify this
  26. class JPH_EXPORT Semaphore
  27. {
  28. public:
  29. /// Constructor
  30. Semaphore();
  31. ~Semaphore();
  32. /// Release the semaphore, signaling the thread waiting on the barrier that there may be work
  33. void Release(uint inNumber = 1);
  34. /// Acquire the semaphore inNumber times
  35. void Acquire(uint inNumber = 1);
  36. /// Get the current value of the semaphore
  37. inline int GetValue() const { return mCount.load(std::memory_order_relaxed); }
  38. private:
  39. #if defined(JPH_PLATFORM_WINDOWS) || defined(JPH_USE_PTHREADS) || defined(JPH_USE_GRAND_CENTRAL_DISPATCH) || defined(JPH_PLATFORM_BLUE)
  40. #ifdef JPH_PLATFORM_WINDOWS
  41. using SemaphoreType = void *;
  42. #elif defined(JPH_USE_PTHREADS)
  43. using SemaphoreType = sem_t;
  44. #elif defined(JPH_USE_GRAND_CENTRAL_DISPATCH)
  45. using SemaphoreType = dispatch_semaphore_t;
  46. #elif defined(JPH_PLATFORM_BLUE)
  47. using SemaphoreType = JPH_PLATFORM_BLUE_SEMAPHORE;
  48. #endif
  49. alignas(JPH_CACHE_LINE_SIZE) atomic<int> 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.
  50. 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
  51. #else
  52. // Other platforms: Emulate a semaphore using a mutex, condition variable and count
  53. std::mutex mLock;
  54. std::condition_variable mWaitVariable;
  55. atomic<int> mCount { 0 };
  56. #endif
  57. };
  58. JPH_NAMESPACE_END