Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace the half-lock with helping strategy #50

Merged
merged 19 commits into from
Jan 3, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Playing with inlining
Seems like minor perf improvements
  • Loading branch information
vorner committed Jan 1, 2021
commit 1a9a3d7eee2dc528d25b65aa8974da6a52518379
1 change: 1 addition & 0 deletions src/debt/fast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ impl Slots {
/// Try to allocate one slot and get the pointer in it.
///
/// Fails if there are no free slots.
#[inline]
pub(super) fn get_debt(&self, ptr: usize, local: &Local) -> Option<&Debt> {
// Trick with offsets: we rotate through the slots (save the value from last time)
// so successive leases are likely to succeed on the first attempt (or soon after)
Expand Down
1 change: 1 addition & 0 deletions src/debt/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ impl LocalNode {
///
/// This is technically lock-free on the first call in a given thread and wait-free on all the
/// other accesses.
#[inline]
pub(crate) fn new_fast(&self, ptr: usize) -> Option<&'static Debt> {
let node = &self.node.get().expect("LocalNode::with ensures it is set");
assert_eq!(node.in_use.load(Relaxed), NODE_USED);
Expand Down
1 change: 1 addition & 0 deletions src/debt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ impl Debt {
/// * It also relies on the fact the same thing is not stuffed both inside an `Arc` and `Rc` or
/// something like that, but that sounds like a reasonable assumption. Someone storing it
/// through `ArcSwap<T>` and someone else with `ArcSwapOption<T>` will work.
#[inline]
pub(crate) fn pay<T: RefCnt>(&self, ptr: *const T::Base) -> bool {
self.0
// If we don't change anything because there's something else, Relaxed is fine.
Expand Down
6 changes: 6 additions & 0 deletions src/strategy/hybrid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ impl<T: RefCnt> HybridProtection<T> {
}
}

#[inline]
fn attempt(node: &LocalNode, storage: &AtomicPtr<T::Base>) -> Option<Self> {
// Relaxed is good enough here, see the Acquire below
let ptr = storage.load(Relaxed);
Expand Down Expand Up @@ -71,12 +72,14 @@ impl<T: RefCnt> HybridProtection<T> {
}
}

#[inline]
fn as_ptr(&self) -> *const T::Base {
T::as_ptr(self.ptr.deref())
}
}

impl<T: RefCnt> Drop for HybridProtection<T> {
#[inline]
fn drop(&mut self) {
match self.debt.take() {
// We have our own copy of Arc, so we don't need a protection. Do nothing (but release
Expand All @@ -99,13 +102,15 @@ impl<T: RefCnt> Drop for HybridProtection<T> {
}

impl<T: RefCnt> Protected<T> for HybridProtection<T> {
#[inline]
fn from_inner(ptr: T) -> Self {
Self {
debt: None,
ptr: ManuallyDrop::new(ptr),
}
}

#[inline]
fn into_inner(mut self) -> T {
// Drop any debt and release any lock held by the given guard and return a
// full-featured value that even can outlive the ArcSwap it originated from.
Expand All @@ -128,6 +133,7 @@ impl<T: RefCnt> Protected<T> for HybridProtection<T> {
}

impl<T: RefCnt> Borrow<T> for HybridProtection<T> {
#[inline]
fn borrow(&self) -> &T {
&self.ptr
}
Expand Down