123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179 |
- #ifndef BOOST_UNORDERED_DETAIL_FOA_RW_SPINLOCK_HPP_INCLUDED
- #define BOOST_UNORDERED_DETAIL_FOA_RW_SPINLOCK_HPP_INCLUDED
- #include <boost/core/yield_primitives.hpp>
- #include <atomic>
- #include <cstdint>
- namespace boost{
- namespace unordered{
- namespace detail{
- namespace foa{
- class rw_spinlock
- {
- private:
-
-
-
- static constexpr std::uint32_t locked_exclusive_mask = 1u << 31;
- static constexpr std::uint32_t writer_pending_mask = 1u << 30;
- static constexpr std::uint32_t reader_lock_count_mask = writer_pending_mask - 1;
- std::atomic<std::uint32_t> state_ = {};
- private:
-
-
- static void yield( unsigned k ) noexcept
- {
- unsigned const sleep_every = 1024;
- k %= sleep_every;
- if( k < 5 )
- {
-
-
-
-
- unsigned const pause_count = 1u << k;
- for( unsigned i = 0; i < pause_count; ++i )
- {
- boost::core::sp_thread_pause();
- }
- }
- else if( k < sleep_every - 1 )
- {
-
-
- boost::core::sp_thread_yield();
- }
- else
- {
-
-
- boost::core::sp_thread_sleep();
- }
- }
- public:
- bool try_lock_shared() noexcept
- {
- std::uint32_t st = state_.load( std::memory_order_relaxed );
- if( st >= reader_lock_count_mask )
- {
-
- return false;
- }
- std::uint32_t newst = st + 1;
- return state_.compare_exchange_strong( st, newst, std::memory_order_acquire, std::memory_order_relaxed );
- }
- void lock_shared() noexcept
- {
- for( unsigned k = 0; ; ++k )
- {
- std::uint32_t st = state_.load( std::memory_order_relaxed );
- 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;
- }
- yield( k );
- }
- }
- void unlock_shared() noexcept
- {
-
- state_.fetch_sub( 1, std::memory_order_release );
-
-
- }
- bool try_lock() noexcept
- {
- std::uint32_t st = state_.load( std::memory_order_relaxed );
- if( st & locked_exclusive_mask )
- {
-
- return false;
- }
- if( st & reader_lock_count_mask )
- {
-
- return false;
- }
- std::uint32_t newst = locked_exclusive_mask;
- return state_.compare_exchange_strong( st, newst, std::memory_order_acquire, std::memory_order_relaxed );
- }
- void lock() noexcept
- {
- for( unsigned k = 0; ; ++k )
- {
- std::uint32_t st = state_.load( std::memory_order_relaxed );
- if( st & locked_exclusive_mask )
- {
-
- }
- else if( ( st & reader_lock_count_mask ) == 0 )
- {
-
- 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 & writer_pending_mask )
- {
-
- }
- else
- {
-
- std::uint32_t newst = st | writer_pending_mask;
- state_.compare_exchange_weak( st, newst, std::memory_order_relaxed, std::memory_order_relaxed );
- }
- yield( k );
- }
- }
- void unlock() noexcept
- {
-
- state_.store( 0, std::memory_order_release );
- }
- };
- }
- }
- }
- }
- #endif
|