mutex.h 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. // Copyright 2009-2021 Intel Corporation
  2. // SPDX-License-Identifier: Apache-2.0
  3. #pragma once
  4. #include "platform.h"
  5. #include "intrinsics.h"
  6. #include "atomic.h"
  7. #define CPU_CACHELINE_SIZE 64
  8. namespace embree
  9. {
  10. /*! system mutex */
  11. class MutexSys {
  12. friend struct ConditionImplementation;
  13. public:
  14. MutexSys();
  15. ~MutexSys();
  16. private:
  17. MutexSys (const MutexSys& other) DELETED; // do not implement
  18. MutexSys& operator= (const MutexSys& other) DELETED; // do not implement
  19. public:
  20. void lock();
  21. bool try_lock();
  22. void unlock();
  23. protected:
  24. void* mutex;
  25. };
  26. /*! spinning mutex */
  27. class SpinLock
  28. {
  29. public:
  30. SpinLock ()
  31. : flag(false) {}
  32. __forceinline bool isLocked() {
  33. return flag.load();
  34. }
  35. __forceinline void lock()
  36. {
  37. while (true)
  38. {
  39. while (flag.load())
  40. {
  41. _mm_pause();
  42. _mm_pause();
  43. }
  44. bool expected = false;
  45. if (flag.compare_exchange_strong(expected,true,std::memory_order_acquire))
  46. break;
  47. }
  48. }
  49. __forceinline bool try_lock()
  50. {
  51. bool expected = false;
  52. if (flag.load() != expected) {
  53. return false;
  54. }
  55. return flag.compare_exchange_strong(expected,true,std::memory_order_acquire);
  56. }
  57. __forceinline void unlock() {
  58. flag.store(false,std::memory_order_release);
  59. }
  60. __forceinline void wait_until_unlocked()
  61. {
  62. while(flag.load())
  63. {
  64. _mm_pause();
  65. _mm_pause();
  66. }
  67. }
  68. public:
  69. atomic<bool> flag;
  70. };
  71. class PaddedSpinLock : public SpinLock
  72. {
  73. private:
  74. MAYBE_UNUSED char padding[CPU_CACHELINE_SIZE - sizeof(SpinLock)];
  75. };
  76. /*! safe mutex lock and unlock helper */
  77. template<typename Mutex> class Lock {
  78. public:
  79. Lock (Mutex& mutex) : mutex(mutex), locked(true) { mutex.lock(); }
  80. Lock (Mutex& mutex, bool locked) : mutex(mutex), locked(locked) {}
  81. ~Lock() { if (locked) mutex.unlock(); }
  82. __forceinline void lock() { assert(!locked); locked = true; mutex.lock(); }
  83. __forceinline bool isLocked() const { return locked; }
  84. protected:
  85. Mutex& mutex;
  86. bool locked;
  87. };
  88. }