Semaphore.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. // Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
  2. // SPDX-FileCopyrightText: 2023 Jorrit Rouwe
  3. // SPDX-License-Identifier: MIT
  4. #include <Jolt/Jolt.h>
  5. #include <Jolt/Core/Semaphore.h>
  6. #include <Jolt/Core/IncludeWindows.h>
  7. JPH_NAMESPACE_BEGIN
  8. Semaphore::Semaphore()
  9. {
  10. #ifdef JPH_PLATFORM_WINDOWS
  11. mSemaphore = CreateSemaphore(nullptr, 0, INT_MAX, nullptr);
  12. if (mSemaphore == nullptr)
  13. {
  14. Trace("Failed to create semaphore");
  15. std::abort();
  16. }
  17. #elif defined(JPH_USE_PTHREADS)
  18. int ret = sem_init(&mSemaphore, 0, 0);
  19. if (ret == -1)
  20. {
  21. Trace("Failed to create semaphore");
  22. std::abort();
  23. }
  24. #elif defined(JPH_USE_GRAND_CENTRAL_DISPATCH)
  25. mSemaphore = dispatch_semaphore_create(0);
  26. if (mSemaphore == nullptr)
  27. {
  28. Trace("Failed to create semaphore");
  29. std::abort();
  30. }
  31. #elif defined(JPH_PLATFORM_BLUE)
  32. if (!JPH_PLATFORM_BLUE_SEMAPHORE_INIT(mSemaphore))
  33. {
  34. Trace("Failed to create semaphore");
  35. std::abort();
  36. }
  37. #endif
  38. }
  39. Semaphore::~Semaphore()
  40. {
  41. #ifdef JPH_PLATFORM_WINDOWS
  42. CloseHandle(mSemaphore);
  43. #elif defined(JPH_USE_PTHREADS)
  44. sem_destroy(&mSemaphore);
  45. #elif defined(JPH_USE_GRAND_CENTRAL_DISPATCH)
  46. dispatch_release(mSemaphore);
  47. #elif defined(JPH_PLATFORM_BLUE)
  48. JPH_PLATFORM_BLUE_SEMAPHORE_DESTROY(mSemaphore);
  49. #endif
  50. }
  51. void Semaphore::Release(uint inNumber)
  52. {
  53. JPH_ASSERT(inNumber > 0);
  54. #if defined(JPH_PLATFORM_WINDOWS) || defined(JPH_USE_PTHREADS) || defined(JPH_USE_GRAND_CENTRAL_DISPATCH) || defined(JPH_PLATFORM_BLUE)
  55. int old_value = mCount.fetch_add(inNumber, std::memory_order_release);
  56. if (old_value < 0)
  57. {
  58. int new_value = old_value + (int)inNumber;
  59. int num_to_release = min(new_value, 0) - old_value;
  60. #ifdef JPH_PLATFORM_WINDOWS
  61. ::ReleaseSemaphore(mSemaphore, num_to_release, nullptr);
  62. #elif defined(JPH_USE_PTHREADS)
  63. for (int i = 0; i < num_to_release; ++i)
  64. sem_post(&mSemaphore);
  65. #elif defined(JPH_USE_GRAND_CENTRAL_DISPATCH)
  66. for (int i = 0; i < num_to_release; ++i)
  67. dispatch_semaphore_signal(mSemaphore);
  68. #elif defined(JPH_PLATFORM_BLUE)
  69. JPH_PLATFORM_BLUE_SEMAPHORE_SIGNAL(mSemaphore, num_to_release);
  70. #endif
  71. }
  72. #else
  73. std::lock_guard lock(mLock);
  74. mCount.fetch_add(inNumber, std::memory_order_relaxed);
  75. if (inNumber > 1)
  76. mWaitVariable.notify_all();
  77. else
  78. mWaitVariable.notify_one();
  79. #endif
  80. }
  81. void Semaphore::Acquire(uint inNumber)
  82. {
  83. JPH_ASSERT(inNumber > 0);
  84. #if defined(JPH_PLATFORM_WINDOWS) || defined(JPH_USE_PTHREADS) || defined(JPH_USE_GRAND_CENTRAL_DISPATCH) || defined(JPH_PLATFORM_BLUE)
  85. int old_value = mCount.fetch_sub(inNumber, std::memory_order_acquire);
  86. int new_value = old_value - (int)inNumber;
  87. if (new_value < 0)
  88. {
  89. int num_to_acquire = min(old_value, 0) - new_value;
  90. #ifdef JPH_PLATFORM_WINDOWS
  91. for (int i = 0; i < num_to_acquire; ++i)
  92. WaitForSingleObject(mSemaphore, INFINITE);
  93. #elif defined(JPH_USE_PTHREADS)
  94. for (int i = 0; i < num_to_acquire; ++i)
  95. sem_wait(&mSemaphore);
  96. #elif defined(JPH_USE_GRAND_CENTRAL_DISPATCH)
  97. for (int i = 0; i < num_to_acquire; ++i)
  98. dispatch_semaphore_wait(mSemaphore, DISPATCH_TIME_FOREVER);
  99. #elif defined(JPH_PLATFORM_BLUE)
  100. JPH_PLATFORM_BLUE_SEMAPHORE_WAIT(mSemaphore, num_to_acquire);
  101. #endif
  102. }
  103. #else
  104. std::unique_lock lock(mLock);
  105. mWaitVariable.wait(lock, [this, inNumber]() {
  106. return mCount.load(std::memory_order_relaxed) >= int(inNumber);
  107. });
  108. mCount.fetch_sub(inNumber, std::memory_order_relaxed);
  109. #endif
  110. }
  111. JPH_NAMESPACE_END