123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 |
- #ifndef BOOST_FIBERS_SPINLOCK_TTAS_H
- #define BOOST_FIBERS_SPINLOCK_TTAS_H
- #include <algorithm>
- #include <atomic>
- #include <chrono>
- #include <cmath>
- #include <random>
- #include <thread>
- #include <boost/fiber/detail/config.hpp>
- #include <boost/fiber/detail/cpu_relax.hpp>
- #include <boost/fiber/detail/spinlock_status.hpp>
- namespace boost {
- namespace fibers {
- namespace detail {
- class spinlock_ttas {
- private:
- template< typename FBSplk >
- friend class spinlock_rtm;
- std::atomic< spinlock_status > state_{ spinlock_status::unlocked };
- public:
- spinlock_ttas() = default;
- spinlock_ttas( spinlock_ttas const&) = delete;
- spinlock_ttas & operator=( spinlock_ttas const&) = delete;
- void lock() noexcept {
- static thread_local std::minstd_rand generator{ std::random_device{}() };
- std::size_t collisions = 0 ;
- for (;;) {
-
-
-
-
-
- std::size_t retries = 0;
-
-
-
-
-
- while ( spinlock_status::locked == state_.load( std::memory_order_relaxed) ) {
- #if !defined(BOOST_FIBERS_SPIN_SINGLE_CORE)
- if ( BOOST_FIBERS_SPIN_BEFORE_SLEEP0 > retries) {
- ++retries;
-
-
-
-
-
- cpu_relax();
- } else if ( BOOST_FIBERS_SPIN_BEFORE_YIELD > retries) {
- ++retries;
-
-
-
-
- static constexpr std::chrono::microseconds us0{ 0 };
- std::this_thread::sleep_for( us0);
- } else {
-
-
-
- std::this_thread::yield();
- }
- #else
- std::this_thread::yield();
- #endif
- }
-
-
- if ( spinlock_status::locked == state_.exchange( spinlock_status::locked, std::memory_order_acquire) ) {
-
-
-
- std::uniform_int_distribution< std::size_t > distribution{
- 0, static_cast< std::size_t >( 1) << (std::min)(collisions, static_cast< std::size_t >( BOOST_FIBERS_CONTENTION_WINDOW_THRESHOLD)) };
- const std::size_t z = distribution( generator);
- ++collisions;
- for ( std::size_t i = 0; i < z; ++i) {
-
-
- cpu_relax();
- }
- } else {
-
- break;
- }
- }
- }
- bool try_lock() noexcept {
- return spinlock_status::unlocked == state_.exchange( spinlock_status::locked, std::memory_order_acquire);
- }
- void unlock() noexcept {
- state_.store( spinlock_status::unlocked, std::memory_order_release);
- }
- };
- }}}
- #endif
|