File indexing completed on 2025-07-30 08:46:18
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #ifndef __TBB_detail__rtm_rw_mutex_H
0018 #define __TBB_detail__rtm_rw_mutex_H
0019
0020 #include "_assert.h"
0021 #include "_utils.h"
0022 #include "../spin_rw_mutex.h"
0023
0024 #include <atomic>
0025
0026 namespace tbb {
0027 namespace detail {
0028
0029 namespace r1 {
0030 struct rtm_rw_mutex_impl;
0031 }
0032
0033 namespace d1 {
0034
0035 constexpr std::size_t speculation_granularity = 64;
0036 #if _MSC_VER && !defined(__INTEL_COMPILER)
0037
0038 #pragma warning (push)
0039 #pragma warning (disable: 4324)
0040 #endif
0041
0042
0043
0044 class alignas(max_nfs_size) rtm_rw_mutex : private spin_rw_mutex {
0045 friend struct r1::rtm_rw_mutex_impl;
0046 private:
0047 enum class rtm_type {
0048 rtm_not_in_mutex,
0049 rtm_transacting_reader,
0050 rtm_transacting_writer,
0051 rtm_real_reader,
0052 rtm_real_writer
0053 };
0054 public:
0055
0056 rtm_rw_mutex() noexcept : write_flag(false) {
0057 create_itt_sync(this, "tbb::speculative_spin_rw_mutex", "");
0058 }
0059
0060
0061 ~rtm_rw_mutex() = default;
0062
0063
0064 class scoped_lock {
0065 friend struct r1::rtm_rw_mutex_impl;
0066 public:
0067
0068
0069 constexpr scoped_lock() : m_mutex(nullptr), m_transaction_state(rtm_type::rtm_not_in_mutex) {}
0070
0071
0072 scoped_lock(rtm_rw_mutex& m, bool write = true) : m_mutex(nullptr), m_transaction_state(rtm_type::rtm_not_in_mutex) {
0073 acquire(m, write);
0074 }
0075
0076
0077 ~scoped_lock() {
0078 if(m_transaction_state != rtm_type::rtm_not_in_mutex) {
0079 release();
0080 }
0081 }
0082
0083
0084 scoped_lock(const scoped_lock&) = delete;
0085 scoped_lock& operator=(const scoped_lock&) = delete;
0086
0087
0088 inline void acquire(rtm_rw_mutex& m, bool write = true);
0089
0090
0091 inline bool try_acquire(rtm_rw_mutex& m, bool write = true);
0092
0093
0094 inline void release();
0095
0096
0097
0098 inline bool upgrade_to_writer();
0099
0100
0101 inline bool downgrade_to_reader();
0102
0103 inline bool is_writer() const;
0104 private:
0105 rtm_rw_mutex* m_mutex;
0106 rtm_type m_transaction_state;
0107 };
0108
0109
0110 static constexpr bool is_rw_mutex = true;
0111 static constexpr bool is_recursive_mutex = false;
0112 static constexpr bool is_fair_mutex = false;
0113
0114 private:
0115 alignas(speculation_granularity) std::atomic<bool> write_flag;
0116 };
0117
0118 #if _MSC_VER && !defined(__INTEL_COMPILER)
0119 #pragma warning (pop)
0120 #endif
0121
0122 }
0123
0124 namespace r1 {
0125
0126
0127 TBB_EXPORT void __TBB_EXPORTED_FUNC acquire_writer(d1::rtm_rw_mutex&, d1::rtm_rw_mutex::scoped_lock&, bool only_speculate = false);
0128
0129
0130 TBB_EXPORT void __TBB_EXPORTED_FUNC acquire_reader(d1::rtm_rw_mutex&, d1::rtm_rw_mutex::scoped_lock&, bool only_speculate = false);
0131
0132 TBB_EXPORT bool __TBB_EXPORTED_FUNC upgrade(d1::rtm_rw_mutex::scoped_lock&);
0133
0134 TBB_EXPORT bool __TBB_EXPORTED_FUNC downgrade(d1::rtm_rw_mutex::scoped_lock&);
0135
0136 TBB_EXPORT bool __TBB_EXPORTED_FUNC try_acquire_writer(d1::rtm_rw_mutex&, d1::rtm_rw_mutex::scoped_lock&);
0137
0138 TBB_EXPORT bool __TBB_EXPORTED_FUNC try_acquire_reader(d1::rtm_rw_mutex&, d1::rtm_rw_mutex::scoped_lock&);
0139
0140 TBB_EXPORT void __TBB_EXPORTED_FUNC release(d1::rtm_rw_mutex::scoped_lock&);
0141 }
0142
0143 namespace d1 {
0144
0145 void rtm_rw_mutex::scoped_lock::acquire(rtm_rw_mutex& m, bool write) {
0146 __TBB_ASSERT(!m_mutex, "lock is already acquired");
0147 if (write) {
0148 r1::acquire_writer(m, *this);
0149 } else {
0150 r1::acquire_reader(m, *this);
0151 }
0152 }
0153
0154
0155 bool rtm_rw_mutex::scoped_lock::try_acquire(rtm_rw_mutex& m, bool write) {
0156 __TBB_ASSERT(!m_mutex, "lock is already acquired");
0157 if (write) {
0158 return r1::try_acquire_writer(m, *this);
0159 } else {
0160 return r1::try_acquire_reader(m, *this);
0161 }
0162 }
0163
0164
0165 void rtm_rw_mutex::scoped_lock::release() {
0166 __TBB_ASSERT(m_mutex, "lock is not acquired");
0167 __TBB_ASSERT(m_transaction_state != rtm_type::rtm_not_in_mutex, "lock is not acquired");
0168 return r1::release(*this);
0169 }
0170
0171
0172
0173 bool rtm_rw_mutex::scoped_lock::upgrade_to_writer() {
0174 __TBB_ASSERT(m_mutex, "lock is not acquired");
0175 if (m_transaction_state == rtm_type::rtm_transacting_writer || m_transaction_state == rtm_type::rtm_real_writer) {
0176 return true;
0177 }
0178 return r1::upgrade(*this);
0179 }
0180
0181
0182 bool rtm_rw_mutex::scoped_lock::downgrade_to_reader() {
0183 __TBB_ASSERT(m_mutex, "lock is not acquired");
0184 if (m_transaction_state == rtm_type::rtm_transacting_reader || m_transaction_state == rtm_type::rtm_real_reader) {
0185 return true;
0186 }
0187 return r1::downgrade(*this);
0188 }
0189
0190 bool rtm_rw_mutex::scoped_lock::is_writer() const {
0191 __TBB_ASSERT(m_mutex, "lock is not acquired");
0192 return m_transaction_state == rtm_type::rtm_transacting_writer || m_transaction_state == rtm_type::rtm_real_writer;
0193 }
0194
0195 #if TBB_USE_PROFILING_TOOLS
0196 inline void set_name(rtm_rw_mutex& obj, const char* name) {
0197 itt_set_sync_name(&obj, name);
0198 }
0199 #if (_WIN32||_WIN64)
0200 inline void set_name(rtm_rw_mutex& obj, const wchar_t* name) {
0201 itt_set_sync_name(&obj, name);
0202 }
0203 #endif
0204 #else
0205 inline void set_name(rtm_rw_mutex&, const char*) {}
0206 #if (_WIN32||_WIN64)
0207 inline void set_name(rtm_rw_mutex&, const wchar_t*) {}
0208 #endif
0209 #endif
0210
0211 }
0212 }
0213 }
0214
0215 #endif