diff --git a/include/boost/unordered/detail/foa/rw_spinlock.hpp b/include/boost/unordered/detail/foa/rw_spinlock.hpp index 132c68dd..a429e5e0 100644 --- a/include/boost/unordered/detail/foa/rw_spinlock.hpp +++ b/include/boost/unordered/detail/foa/rw_spinlock.hpp @@ -21,7 +21,11 @@ private: // bit 31: locked exclusive // bit 30: writer pending - // bit 29..: reader lock count + // bit 29..0: reader lock count + + static constexpr std::uint32_t locked_exclusive_mask = 1u << 31; // 0x8000'0000 + static constexpr std::uint32_t writer_pending_mask = 1u << 30; // 0x4000'0000 + static constexpr std::uint32_t reader_lock_count_mask = writer_pending_mask - 1; // 0x3FFF'FFFF std::atomic state_ = {}; @@ -36,7 +40,7 @@ public: { std::uint32_t st = state_.load( std::memory_order_relaxed ); - if( st >= 0x3FFF'FFFF ) + if( st >= reader_lock_count_mask ) { // either bit 31 set, bit 30 set, or reader count is max return false; @@ -54,7 +58,7 @@ public: { std::uint32_t st = state_.load( std::memory_order_relaxed ); - if( st < 0x3FFF'FFFF ) + if( st < reader_lock_count_mask ) { std::uint32_t newst = st + 1; if( state_.compare_exchange_weak( st, newst, std::memory_order_acquire, std::memory_order_relaxed ) ) return; @@ -81,19 +85,19 @@ public: { std::uint32_t st = state_.load( std::memory_order_relaxed ); - if( st & 0x8000'0000 ) + if( st & locked_exclusive_mask ) { // locked exclusive return false; } - if( st & 0x3FFF'FFFF ) + if( st & reader_lock_count_mask ) { // locked shared return false; } - std::uint32_t newst = 0x8000'0000; + std::uint32_t newst = locked_exclusive_mask; return state_.compare_exchange_strong( st, newst, std::memory_order_acquire, std::memory_order_relaxed ); } @@ -105,18 +109,18 @@ public: { std::uint32_t st = state_.load( std::memory_order_relaxed ); - if( st & 0x8000'0000 ) + if( st & locked_exclusive_mask ) { // locked exclusive, spin } - else if( ( st & 0x3FFF'FFFF ) == 0 ) + else if( ( st & reader_lock_count_mask ) == 0 ) { // not locked exclusive, not locked shared, try to lock - std::uint32_t newst = 0x8000'0000; + std::uint32_t newst = locked_exclusive_mask; if( state_.compare_exchange_weak( st, newst, std::memory_order_acquire, std::memory_order_relaxed ) ) return; } - else if( st & 0x4000'000 ) + else if( st & writer_pending_mask ) { // writer pending bit already set, nothing to do } @@ -124,7 +128,7 @@ public: { // locked shared, set writer pending bit - std::uint32_t newst = st | 0x4000'0000; + std::uint32_t newst = st | writer_pending_mask; state_.compare_exchange_weak( st, newst, std::memory_order_relaxed, std::memory_order_relaxed ); } @@ -138,19 +142,19 @@ public: for( ;; ) { - if( st & 0x8000'0000 ) + if( st & locked_exclusive_mask ) { // locked exclusive, nothing to do break; } - else if( ( st & 0x3FFF'FFFF ) == 0 ) + else if( ( st & reader_lock_count_mask ) == 0 ) { // lock free, try to take it - std::uint32_t newst = 0x8000'0000; + std::uint32_t newst = locked_exclusive_mask; if( state_.compare_exchange_weak( st, newst, std::memory_order_acquire, std::memory_order_relaxed ) ) return; } - else if( ( st & 0x4000'0000 ) == 0 ) + else if( ( st & writer_pending_mask ) == 0 ) { // writer pending bit already clear, nothing to do break; @@ -159,7 +163,7 @@ public: { // clear writer pending bit - std::uint32_t newst = st & ~0x4000'0000u; + std::uint32_t newst = st & ~writer_pending_mask; if( state_.compare_exchange_weak( st, newst, std::memory_order_relaxed, std::memory_order_relaxed ) ) break; } }