You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

lock.h 3.5 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /**
  2. * Copyright 2019 Huawei Technologies Co., Ltd
  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. #ifndef DATASET_UTIL_LOCK_H_
  17. #define DATASET_UTIL_LOCK_H_
  18. #include <atomic>
  19. #include <condition_variable>
  20. #include <mutex>
  21. namespace mindspore {
  22. namespace dataset {
  23. class SpinLock {
  24. public:
  25. void Lock();
  26. bool TryLock();
  27. void Unlock() noexcept;
  28. SpinLock() : val_(kUnlocked) {}
  29. SpinLock(const SpinLock &) = delete;
  30. SpinLock(SpinLock &&) = delete;
  31. ~SpinLock() = default;
  32. SpinLock &operator=(const SpinLock &) = delete;
  33. SpinLock &operator=(SpinLock &&) = delete;
  34. private:
  35. static constexpr int kUnlocked = 0;
  36. static constexpr int kLocked = 1;
  37. std::atomic<int> val_;
  38. };
  39. // C++11 has no shared mutex. The following class is an alternative. It favors writer and is suitable for the case
  40. // where writer is rare.
  41. class RWLock {
  42. public:
  43. RWLock() : status_(0), waiting_readers_(0), waiting_writers_(0) {}
  44. RWLock(const RWLock &) = delete;
  45. RWLock(RWLock &&) = delete;
  46. ~RWLock() = default;
  47. RWLock &operator=(const RWLock &) = delete;
  48. RWLock &operator=(RWLock &&) = delete;
  49. void LockShared();
  50. void LockExclusive() {
  51. std::unique_lock<std::mutex> lck(mtx_);
  52. waiting_writers_ += 1;
  53. write_cv_.wait(lck, [this]() { return status_ == 0; });
  54. waiting_writers_ -= 1;
  55. status_ = -1;
  56. }
  57. void Unlock() noexcept;
  58. // Upgrade a shared lock to exclusive lock
  59. void Upgrade();
  60. // Downgrade an exclusive lock to shared lock
  61. void Downgrade();
  62. private:
  63. // -1 : one writer
  64. // 0 : no reader and no writer
  65. // n > 0 : n reader
  66. int32_t status_;
  67. int32_t waiting_readers_;
  68. int32_t waiting_writers_;
  69. std::mutex mtx_;
  70. std::condition_variable read_cv_;
  71. std::condition_variable write_cv_;
  72. };
  73. // A Wrapper for RWLock. The destructor will release the lock if we own it.
  74. class SharedLock {
  75. public:
  76. explicit SharedLock(RWLock *rw);
  77. ~SharedLock();
  78. SharedLock(const SharedLock &) = delete;
  79. SharedLock(SharedLock &&) = delete;
  80. SharedLock &operator=(const SharedLock &) = delete;
  81. SharedLock &operator=(SharedLock &&) = delete;
  82. void Unlock();
  83. void Lock();
  84. void Upgrade();
  85. void Downgrade();
  86. private:
  87. RWLock *rw_;
  88. bool ownlock_;
  89. };
  90. class UniqueLock {
  91. public:
  92. explicit UniqueLock(RWLock *rw);
  93. ~UniqueLock();
  94. UniqueLock(const UniqueLock &) = delete;
  95. UniqueLock(UniqueLock &&) = delete;
  96. UniqueLock &operator=(const UniqueLock &) = delete;
  97. UniqueLock &operator=(UniqueLock &&) = delete;
  98. void Unlock();
  99. void Lock();
  100. private:
  101. RWLock *rw_;
  102. bool ownlock_;
  103. };
  104. class LockGuard {
  105. public:
  106. explicit LockGuard(SpinLock *lock);
  107. ~LockGuard();
  108. LockGuard(const LockGuard &) = delete;
  109. LockGuard(LockGuard &&) = delete;
  110. LockGuard &operator=(const LockGuard &) = delete;
  111. LockGuard &operator=(LockGuard &&) = delete;
  112. void Unlock();
  113. void Lock();
  114. private:
  115. SpinLock *lck_;
  116. bool own_lock_;
  117. };
  118. } // namespace dataset
  119. } // namespace mindspore
  120. #endif // DATASET_UTIL_LOCK_H_