Warning, file /include/oneapi/tbb/spin_rw_mutex.h was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #ifndef __TBB_spin_rw_mutex_H
0018 #define __TBB_spin_rw_mutex_H
0019
0020 #include "detail/_namespace_injection.h"
0021 #include "detail/_mutex_common.h"
0022
0023 #include "profiling.h"
0024
0025 #include "detail/_assert.h"
0026 #include "detail/_utils.h"
0027 #include "detail/_scoped_lock.h"
0028
0029 #include <atomic>
0030
0031 namespace tbb {
0032 namespace detail {
0033 namespace d1 {
0034
0035 #if __TBB_TSX_INTRINSICS_PRESENT
0036 class rtm_rw_mutex;
0037 #endif
0038
0039
0040
0041 class spin_rw_mutex {
0042 public:
0043
0044 spin_rw_mutex() noexcept : m_state(0) {
0045 create_itt_sync(this, "tbb::spin_rw_mutex", "");
0046 }
0047
0048
0049 ~spin_rw_mutex() {
0050 __TBB_ASSERT(!m_state, "destruction of an acquired mutex");
0051 }
0052
0053
0054 spin_rw_mutex(const spin_rw_mutex&) = delete;
0055 spin_rw_mutex& operator=(const spin_rw_mutex&) = delete;
0056
0057 using scoped_lock = rw_scoped_lock<spin_rw_mutex>;
0058
0059
0060 static constexpr bool is_rw_mutex = true;
0061 static constexpr bool is_recursive_mutex = false;
0062 static constexpr bool is_fair_mutex = false;
0063
0064
0065 void lock() {
0066 call_itt_notify(prepare, this);
0067 for (atomic_backoff backoff; ; backoff.pause()) {
0068 state_type s = m_state.load(std::memory_order_relaxed);
0069 if (!(s & BUSY)) {
0070 if (m_state.compare_exchange_strong(s, WRITER))
0071 break;
0072 backoff.reset();
0073 } else if (!(s & WRITER_PENDING)) {
0074 m_state |= WRITER_PENDING;
0075 }
0076 }
0077 call_itt_notify(acquired, this);
0078 }
0079
0080
0081
0082 bool try_lock() {
0083
0084 state_type s = m_state.load(std::memory_order_relaxed);
0085 if (!(s & BUSY)) {
0086 if (m_state.compare_exchange_strong(s, WRITER)) {
0087 call_itt_notify(acquired, this);
0088 return true;
0089 }
0090 }
0091 return false;
0092 }
0093
0094
0095 void unlock() {
0096 call_itt_notify(releasing, this);
0097 m_state &= READERS;
0098 }
0099
0100
0101 void lock_shared() {
0102 call_itt_notify(prepare, this);
0103 for (atomic_backoff b; ; b.pause()) {
0104 state_type s = m_state.load(std::memory_order_relaxed);
0105 if (!(s & (WRITER | WRITER_PENDING))) {
0106 state_type prev_state = m_state.fetch_add(ONE_READER);
0107 if (!(prev_state & WRITER)) {
0108 break;
0109 }
0110
0111 m_state -= ONE_READER;
0112 }
0113 }
0114 call_itt_notify(acquired, this);
0115 __TBB_ASSERT(m_state & READERS, "invalid state of a read lock: no readers");
0116 }
0117
0118
0119 bool try_lock_shared() {
0120
0121 state_type s = m_state.load(std::memory_order_relaxed);
0122 if (!(s & (WRITER | WRITER_PENDING))) {
0123 state_type prev_state = m_state.fetch_add(ONE_READER);
0124 if (!(prev_state & WRITER)) {
0125 call_itt_notify(acquired, this);
0126 return true;
0127 }
0128
0129 m_state -= ONE_READER;
0130 }
0131 return false;
0132 }
0133
0134
0135 void unlock_shared() {
0136 __TBB_ASSERT(m_state & READERS, "invalid state of a read lock: no readers");
0137 call_itt_notify(releasing, this);
0138 m_state -= ONE_READER;
0139 }
0140
0141 protected:
0142
0143
0144
0145
0146
0147 bool upgrade() {
0148 state_type s = m_state.load(std::memory_order_relaxed);
0149 __TBB_ASSERT(s & READERS, "invalid state before upgrade: no readers ");
0150
0151
0152
0153 while ((s & READERS) == ONE_READER || !(s & WRITER_PENDING)) {
0154 if (m_state.compare_exchange_strong(s, s | WRITER | WRITER_PENDING)) {
0155 atomic_backoff backoff;
0156 while ((m_state.load(std::memory_order_relaxed) & READERS) != ONE_READER) backoff.pause();
0157 __TBB_ASSERT((m_state & (WRITER_PENDING|WRITER)) == (WRITER_PENDING | WRITER), "invalid state when upgrading to writer");
0158
0159 m_state -= (ONE_READER + WRITER_PENDING);
0160 return true;
0161 }
0162 }
0163
0164 unlock_shared();
0165 lock();
0166 return false;
0167 }
0168
0169
0170 void downgrade() {
0171 call_itt_notify(releasing, this);
0172 m_state += (ONE_READER - WRITER);
0173 __TBB_ASSERT(m_state & READERS, "invalid state after downgrade: no readers");
0174 }
0175
0176 using state_type = std::intptr_t;
0177 static constexpr state_type WRITER = 1;
0178 static constexpr state_type WRITER_PENDING = 2;
0179 static constexpr state_type READERS = ~(WRITER | WRITER_PENDING);
0180 static constexpr state_type ONE_READER = 4;
0181 static constexpr state_type BUSY = WRITER | READERS;
0182 friend scoped_lock;
0183
0184
0185
0186
0187 std::atomic<state_type> m_state;
0188 };
0189
0190 #if TBB_USE_PROFILING_TOOLS
0191 inline void set_name(spin_rw_mutex& obj, const char* name) {
0192 itt_set_sync_name(&obj, name);
0193 }
0194 #if (_WIN32||_WIN64)
0195 inline void set_name(spin_rw_mutex& obj, const wchar_t* name) {
0196 itt_set_sync_name(&obj, name);
0197 }
0198 #endif
0199 #else
0200 inline void set_name(spin_rw_mutex&, const char*) {}
0201 #if (_WIN32||_WIN64)
0202 inline void set_name(spin_rw_mutex&, const wchar_t*) {}
0203 #endif
0204 #endif
0205 }
0206 }
0207
0208 inline namespace v1 {
0209 using detail::d1::spin_rw_mutex;
0210 }
0211 namespace profiling {
0212 using detail::d1::set_name;
0213 }
0214 }
0215
0216 #include "detail/_rtm_rw_mutex.h"
0217
0218 namespace tbb {
0219 inline namespace v1 {
0220 #if __TBB_TSX_INTRINSICS_PRESENT
0221 using speculative_spin_rw_mutex = detail::d1::rtm_rw_mutex;
0222 #else
0223 using speculative_spin_rw_mutex = detail::d1::spin_rw_mutex;
0224 #endif
0225 }
0226 }
0227
0228 #endif
0229