mutex.h 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. // ======================================================================== //
  2. // Copyright 2009-2017 Intel Corporation //
  3. // //
  4. // Licensed under the Apache License, Version 2.0 (the "License"); //
  5. // you may not use this file except in compliance with the License. //
  6. // You may obtain a copy of the License at //
  7. // //
  8. // http://www.apache.org/licenses/LICENSE-2.0 //
  9. // //
  10. // Unless required by applicable law or agreed to in writing, software //
  11. // distributed under the License is distributed on an "AS IS" BASIS, //
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
  13. // See the License for the specific language governing permissions and //
  14. // limitations under the License. //
  15. // ======================================================================== //
  16. #pragma once
  17. #include "platform.h"
  18. #include "intrinsics.h"
  19. #include "atomic.h"
  20. namespace embree
  21. {
  22. /*! system mutex */
  23. class MutexSys {
  24. friend struct ConditionImplementation;
  25. public:
  26. MutexSys( void );
  27. ~MutexSys( void );
  28. private:
  29. MutexSys (const MutexSys& other) DELETED; // do not implement
  30. MutexSys& operator= (const MutexSys& other) DELETED; // do not implement
  31. public:
  32. void lock( void );
  33. bool try_lock( void );
  34. void unlock( void );
  35. protected:
  36. void* mutex;
  37. };
  38. /*! spinning mutex */
  39. class SpinLock
  40. {
  41. public:
  42. SpinLock ()
  43. : flag(false) {}
  44. __forceinline bool isLocked() {
  45. return flag.load();
  46. }
  47. __forceinline void lock()
  48. {
  49. while (true)
  50. {
  51. while (flag.load())
  52. {
  53. _mm_pause();
  54. _mm_pause();
  55. }
  56. bool expected = false;
  57. if (flag.compare_exchange_strong(expected,true,std::memory_order_acquire))
  58. break;
  59. }
  60. }
  61. __forceinline bool try_lock()
  62. {
  63. bool expected = false;
  64. if (flag.load() != expected) {
  65. return false;
  66. }
  67. return flag.compare_exchange_strong(expected,true,std::memory_order_acquire);
  68. }
  69. __forceinline void unlock() {
  70. flag.store(false,std::memory_order_release);
  71. }
  72. __forceinline void wait_until_unlocked()
  73. {
  74. while(flag.load())
  75. {
  76. _mm_pause();
  77. _mm_pause();
  78. }
  79. }
  80. public:
  81. atomic<bool> flag;
  82. };
  83. /*! safe mutex lock and unlock helper */
  84. template<typename Mutex> class Lock {
  85. public:
  86. Lock (Mutex& mutex) : mutex(mutex), locked(true) { mutex.lock(); }
  87. Lock (Mutex& mutex, bool locked) : mutex(mutex), locked(locked) {}
  88. ~Lock() { if (locked) mutex.unlock(); }
  89. __forceinline void lock() { assert(!locked); locked = true; mutex.lock(); }
  90. __forceinline bool isLocked() const { return locked; }
  91. protected:
  92. Mutex& mutex;
  93. bool locked;
  94. };
  95. }