summaryrefslogtreecommitdiff
path: root/boost/fiber/detail/spinlock_ttas.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/fiber/detail/spinlock_ttas.hpp')
-rw-r--r--boost/fiber/detail/spinlock_ttas.hpp29
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