diff options
Diffstat (limited to 'boost/fiber/detail/spinlock_ttas.hpp')
-rw-r--r-- | boost/fiber/detail/spinlock_ttas.hpp | 29 |
1 files changed, 16 insertions, 13 deletions
diff --git a/boost/fiber/detail/spinlock_ttas.hpp b/boost/fiber/detail/spinlock_ttas.hpp index d64630d84d..380773ad6d 100644 --- a/boost/fiber/detail/spinlock_ttas.hpp +++ b/boost/fiber/detail/spinlock_ttas.hpp @@ -19,6 +19,11 @@ // https://software.intel.com/en-us/articles/benefitting-power-and-performance-sleep-loops // https://software.intel.com/en-us/articles/long-duration-spin-wait-loops-on-hyper-threading-technology-enabled-intel-processors +#if BOOST_COMP_CLANG +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif + namespace boost { namespace fibers { namespace detail { @@ -30,10 +35,7 @@ private: unlocked }; - // align shared variable 'state_' at cache line to prevent false sharing - alignas(cache_alignment) std::atomic< spinlock_status > state_{ spinlock_status::unlocked }; - // padding to avoid other data one the cacheline of shared variable 'state_' - char pad[cacheline_length]; + std::atomic< spinlock_status > state_{ spinlock_status::unlocked }; public: spinlock_ttas() noexcept = default; @@ -63,20 +65,15 @@ public: // delays the next instruction's execution for a finite period of time (depends on processor family) // the CPU is not under demand, parts of the pipeline are no longer being used // -> reduces the power consumed by the CPU + // -> prevent pipeline stalls cpu_relax(); - } else if ( BOOST_FIBERS_SPIN_MAX_TESTS + 20 > tests) { - ++tests; + } else { // std::this_thread::sleep_for( 0us) has a fairly long instruction path length, // combined with an expensive ring3 to ring 0 transition costing about 1000 cycles // std::this_thread::sleep_for( 0us) lets give up this_thread the remaining part of its time slice // if and only if a thread of equal or greater priority is ready to run static constexpr std::chrono::microseconds us0{ 0 }; std::this_thread::sleep_for( us0); - } else { - // std::this_thread::yield() allows this_thread to give up the remaining part of its time slice, - // but only to another thread on the same processor - // instead of constant checking, a thread only checks if no other useful work is pending - std::this_thread::yield(); } #else std::this_thread::yield(); @@ -89,10 +86,12 @@ public: // utilize 'Binary Exponential Backoff' algorithm // linear_congruential_engine is a random number engine based on Linear congruential generator (LCG) static thread_local std::minstd_rand generator; - const std::size_t z = - std::uniform_int_distribution< std::size_t >{ 0, static_cast< std::size_t >( 1) << collisions }( generator); + static std::uniform_int_distribution< std::size_t > distribution{ 0, static_cast< std::size_t >( 1) << collisions }; + const std::size_t z = distribution( generator); ++collisions; for ( std::size_t i = 0; i < z; ++i) { + // -> reduces the power consumed by the CPU + // -> prevent pipeline stalls cpu_relax(); } } else { @@ -109,4 +108,8 @@ public: }}} +#if BOOST_COMP_CLANG +#pragma clang diagnostic pop +#endif + #endif // BOOST_FIBERS_SPINLOCK_TTAS_H |