Skip to content
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -77,20 +77,18 @@ namespace hpx::detail {
bool set_state(shared_state& s1, shared_state& s) noexcept
{
++s.data.tag;
return s1.value == state.load(std::memory_order_relaxed).value &&
state.compare_exchange_strong(s1, s, std::memory_order_release);
return state.compare_exchange_strong(s1, s, std::memory_order_release,
std::memory_order_relaxed);
}

bool set_state(shared_state& s1, shared_state& s,
std::unique_lock<mutex_type>& lk) noexcept
{
if (s1.value != state.load(std::memory_order_relaxed).value)
return false;

++s.data.tag;

lk = std::unique_lock<mutex_type>(state_change);
if (state.compare_exchange_strong(s1, s, std::memory_order_release))
if (state.compare_exchange_strong(s1, s, std::memory_order_release,
std::memory_order_relaxed))
return true;

lk.unlock();
Expand Down Expand Up @@ -121,9 +119,9 @@ namespace hpx::detail {

bool try_lock_shared()
{
auto s = state.load(std::memory_order_acquire);
while (true)
{
auto s = state.load(std::memory_order_acquire);
if (s.data.exclusive || s.data.exclusive_waiting_blocked)
{
return false;
Expand All @@ -136,15 +134,37 @@ namespace hpx::detail {
{
break;
}
s = s1;
}
Comment thread
hkaiser marked this conversation as resolved.
return true;
}
Comment thread
hkaiser marked this conversation as resolved.

bool try_unlock_shared_fast()
{
auto s = state.load(std::memory_order_acquire);
while (true)
{
if (s.data.exclusive || s.data.exclusive_waiting_blocked ||
s.data.upgrade || s.data.shared_count <= 1)
{
return false;
}

auto s1 = s;
--s.data.shared_count;
if (set_state(s1, s))
{
return true;
}
s = s1;
}
}

void unlock_shared()
{
auto s = state.load(std::memory_order_acquire);
while (true)
{
auto s = state.load(std::memory_order_acquire);
auto s1 = s;

if (--s.data.shared_count == 0)
Expand Down Expand Up @@ -184,14 +204,15 @@ namespace hpx::detail {
{
break;
}
s = s1;
}
}

void lock()
{
auto s = state.load(std::memory_order_acquire);
while (true)
{
auto s = state.load(std::memory_order_acquire);
while (s.data.shared_count != 0 || s.data.exclusive)
{
auto s1 = s;
Expand All @@ -214,14 +235,15 @@ namespace hpx::detail {
{
break;
}
s = s1;
}
}

bool try_lock()
{
auto s = state.load(std::memory_order_acquire);
while (true)
{
auto s = state.load(std::memory_order_acquire);
if (s.data.shared_count || s.data.exclusive)
{
return false;
Expand All @@ -234,15 +256,16 @@ namespace hpx::detail {
{
break;
}
s = s1;
}
return true;
}

void unlock()
{
auto s = state.load(std::memory_order_acquire);
while (true)
{
auto s = state.load(std::memory_order_acquire);
auto s1 = s;

s.data.exclusive = false;
Expand All @@ -255,6 +278,7 @@ namespace hpx::detail {
release_waiters(lk);
break;
}
s = s1;
}
}

Expand Down Expand Up @@ -287,9 +311,9 @@ namespace hpx::detail {

bool try_lock_upgrade()
{
auto s = state.load(std::memory_order_acquire);
while (true)
{
auto s = state.load(std::memory_order_acquire);
if (s.data.exclusive || s.data.exclusive_waiting_blocked ||
s.data.upgrade)
{
Expand All @@ -304,15 +328,16 @@ namespace hpx::detail {
{
break;
}
s = s1;
}
return true;
}

void unlock_upgrade()
{
auto s = state.load(std::memory_order_acquire);
while (true)
{
auto s = state.load(std::memory_order_acquire);
auto s1 = s;

bool release = false;
Expand All @@ -337,6 +362,7 @@ namespace hpx::detail {
{
break;
}
s = s1;
}
}

Expand Down Expand Up @@ -384,9 +410,9 @@ namespace hpx::detail {

void unlock_and_lock_upgrade()
{
auto s = state.load(std::memory_order_acquire);
while (true)
{
auto s = state.load(std::memory_order_acquire);
auto s1 = s;

s.data.exclusive = false;
Expand All @@ -401,14 +427,15 @@ namespace hpx::detail {
release_waiters(lk);
break;
}
s = s1;
}
}

void unlock_and_lock_shared()
{
auto s = state.load(std::memory_order_acquire);
while (true)
{
auto s = state.load(std::memory_order_acquire);
auto s1 = s;

s.data.exclusive = false;
Expand All @@ -422,14 +449,15 @@ namespace hpx::detail {
release_waiters(lk);
break;
}
s = s1;
}
}

bool try_unlock_shared_and_lock()
{
auto s = state.load(std::memory_order_acquire);
while (true)
{
auto s = state.load(std::memory_order_acquire);
if (s.data.exclusive || s.data.exclusive_waiting_blocked ||
s.data.upgrade || s.data.shared_count != 1)
{
Expand All @@ -444,15 +472,16 @@ namespace hpx::detail {
{
break;
}
s = s1;
}
return true;
}

void unlock_upgrade_and_lock_shared()
{
auto s = state.load(std::memory_order_acquire);
while (true)
{
auto s = state.load(std::memory_order_acquire);
auto s1 = s;

s.data.exclusive_waiting_blocked = false;
Expand All @@ -465,6 +494,7 @@ namespace hpx::detail {
release_waiters(lk);
break;
}
s = s1;
}
}

Expand Down Expand Up @@ -509,86 +539,76 @@ namespace hpx::detail {

void lock_shared()
{
auto data = data_;
data->lock_shared();
if (data_->try_lock_shared())
return;
data_->lock_shared();
Comment thread
hkaiser marked this conversation as resolved.
Outdated
}

bool try_lock_shared()
{
auto data = data_;
return data->try_lock_shared();
return data_->try_lock_shared();
Comment thread
hkaiser marked this conversation as resolved.
Outdated
}

void unlock_shared()
{
auto data = data_;
data->unlock_shared();
if (data_->try_unlock_shared_fast())
return;
Comment on lines +557 to +558
Copy link

Copilot AI Apr 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shared_mutex::unlock_shared now attempts try_unlock_shared_fast() and on failure immediately calls unlock_shared(), which re-loads the atomic state and repeats much of the decision logic. For common cases where the shared count is 1 (or upgrade/exclusive-wait flags are set), this adds an extra atomic load/branching to every unlock. Consider folding the fast path into shared_mutex_data::unlock_shared() (single state load) or otherwise structuring it to avoid double-reading the state on the fallback path.

Suggested change
if (data->try_unlock_shared_fast())
return;

Copilot uses AI. Check for mistakes.
data_->unlock_shared();
}

void lock()
{
auto data = data_;
data->lock();
data_->lock();
}

bool try_lock()
{
auto data = data_;
return data->try_lock();
return data_->try_lock();
}

void unlock()
{
auto data = data_;
data->unlock();
data_->unlock();
}

void lock_upgrade()
{
auto data = data_;
data->lock_upgrade();
data_->lock_upgrade();
}

bool try_lock_upgrade()
{
auto data = data_;
return data->try_lock_upgrade();
return data_->try_lock_upgrade();
}

void unlock_upgrade()
{
auto data = data_;
data->unlock_upgrade();
data_->unlock_upgrade();
}

void unlock_upgrade_and_lock()
{
auto data = data_;
data->unlock_upgrade_and_lock();
data_->unlock_upgrade_and_lock();
}

void unlock_and_lock_upgrade()
{
auto data = data_;
data->unlock_and_lock_upgrade();
data_->unlock_and_lock_upgrade();
}

void unlock_and_lock_shared()
{
auto data = data_;
data->unlock_and_lock_shared();
data_->unlock_and_lock_shared();
}

bool try_unlock_shared_and_lock()
{
auto data = data_;
return data->try_unlock_shared_and_lock();
return data_->try_unlock_shared_and_lock();
}

void unlock_upgrade_and_lock_shared()
{
auto data = data_;
data->unlock_upgrade_and_lock_shared();
data_->unlock_upgrade_and_lock_shared();
}
};
} // namespace hpx::detail
Expand Down
2 changes: 2 additions & 0 deletions tests/performance/local/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ set(benchmarks
skynet
wait_all_timings
benchmark_stealing
shared_mutex_overhead
)

set(timed_task_spawn_SOURCES activate_counters.cpp)
Expand Down Expand Up @@ -144,6 +145,7 @@ set(print_heterogeneous_payloads_PARAMETERS NO_HPX_MAIN)
set(skynet_PARAMETERS NO_HPX_MAIN)
set(timed_task_spawn_PARAMETERS NO_HPX_MAIN)
set(benchmark_stealing_PARAMETERS NO_HPX_MAIN)
set(shared_mutex_overhead_PARAMETERS NO_HPX_MAIN)
set(hpx_tls_overhead_PARAMETERS NO_HPX_MAIN)
Comment thread
arpittkhandelwal marked this conversation as resolved.
set(native_tls_overhead_PARAMETERS NO_HPX_MAIN)
set(coroutines_call_overhead_PARAMETERS NO_HPX_MAIN)
Expand Down
Loading
Loading