Skip to content

Commit

Permalink
Merge branch 'wfs' of github.com:vorner/arc-swap into wfs
Browse files Browse the repository at this point in the history
  • Loading branch information
vorner committed Dec 26, 2020
2 parents a13a9b6 + 429f3fd commit a7dab6d
Show file tree
Hide file tree
Showing 10 changed files with 79 additions and 19 deletions.
24 changes: 23 additions & 1 deletion .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -144,4 +144,26 @@ jobs:
- name: Run clippy linter
run: rm Cargo.lock && cargo check

# TODO: Some miri checks
miri:
name: Miri checks
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2

- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: nightly
profile: minimal
default: true
components: "miri"

- name: Restore cache
uses: Swatinem/rust-cache@v1

- name: Run miri
env:
PROPTEST_CASES: "10"
MIRIFLAGS: "-Zmiri-disable-isolation"
run: cargo miri test
6 changes: 5 additions & 1 deletion src/debt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,11 @@ impl Node {
traverse(|node| {
// Try to claim this node. Nothing is synchronized through this atomic, we only
// track if someone claims ownership of it.
if !node.in_use.compare_and_swap(false, true, Ordering::Relaxed) {
let claimed = node
.in_use
.compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed)
.is_ok();
if claimed {
Some(node)
} else {
None
Expand Down
2 changes: 1 addition & 1 deletion src/gen_lock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ pub(crate) fn wait_for_readers<S: LockStorage>(storage: &S) {
let next_gen = gen.wrapping_add(1);
if groups[next_gen % GEN_CNT] == 0 {
// Replace it only if someone else didn't do it in the meantime
gen_idk.compare_and_swap(gen, next_gen, Ordering::Relaxed);
let _ = gen_idk.compare_exchange(gen, next_gen, Ordering::Relaxed, Ordering::Relaxed);
}
for i in 0..GEN_CNT {
seen_group[i] = seen_group[i] || (groups[i] == 0);
Expand Down
7 changes: 5 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -777,9 +777,9 @@ macro_rules! t {
/// Similar to the one in doc tests of the lib, but more times and more intensive (we
/// want to torture it a bit).
#[test]
#[cfg(not(miri))] // Infinitely slow under miri :-(
#[cfg_attr(miri, ignore)] // Takes like 1 or 2 infinities to run under miri
fn publish() {
const READERS: usize = 3;
const READERS: usize = 2;
for _ in 0..ITERATIONS {
let config = AS::<String>::default();
let ended = AtomicUsize::new(0);
Expand Down Expand Up @@ -842,6 +842,9 @@ macro_rules! t {
let shared = AS::from(Arc::clone(&first_value));
const WRITER_CNT: usize = 2;
const READER_CNT: usize = 3;
#[cfg(miri)]
const ITERATIONS: usize = 10;
#[cfg(not(miri))]
const ITERATIONS: usize = 100;
const SEQ: usize = 50;
let barrier = Barrier::new(PanicMode::Poison);
Expand Down
9 changes: 6 additions & 3 deletions src/strategy/gen_lock.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use std::ptr;
use std::sync::atomic::{AtomicPtr, Ordering};

use crate::gen_lock::{self, GenLock, LockStorage};
Expand Down Expand Up @@ -44,8 +43,12 @@ impl<T: RefCnt, L: LockStorage> CaS<T> for GenLockStrategy<L> {
// which ones upfront, so we need to implement safety measures for both.
let lock = GenLock::new(&self.0);

let previous_ptr = storage.compare_and_swap(cur_ptr, new, Ordering::SeqCst);
let swapped = ptr::eq(cur_ptr, previous_ptr);
let swap_result =
storage.compare_exchange(cur_ptr, new, Ordering::SeqCst, Ordering::SeqCst);
let (previous_ptr, swapped) = match swap_result {
Ok(previous) => (previous, true),
Err(previous) => (previous, false),
};

// Drop it here, because:
// * We can't drop it before the compare_and_swap ‒ in such case, it could get recycled,
Expand Down
7 changes: 3 additions & 4 deletions src/strategy/helping.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,12 @@ use std::fmt::{Debug, Formatter, Result as FmtResult};
use std::mem::{self, ManuallyDrop};
use std::ops::Deref;
use std::ptr;
use std::sync::atomic::{AtomicBool, AtomicPtr, AtomicUsize, Ordering};
use std::sync::atomic::Ordering::*;
use std::sync::atomic::{AtomicBool, AtomicPtr, AtomicUsize};

use super::sealed::{InnerStrategy, Protected};
use crate::RefCnt;

use Ordering::*;

/// A wrapper around a node pointer, to un-claim the node on thread shutdown.
struct DebtHead {
// Node for this thread.
Expand Down Expand Up @@ -133,7 +132,7 @@ impl Debt {
//
// The Release works as kind of Mutex. We make sure nothing from the debt-protected
// sections leaks below this point.
.compare_exchange(ptr as usize, NO_DEBT, Ordering::Release, Ordering::Relaxed)
.compare_exchange(ptr as usize, NO_DEBT, Release, Relaxed)
.is_ok()
}

Expand Down
8 changes: 6 additions & 2 deletions src/strategy/hybrid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,12 @@ impl<T: RefCnt, L: LockStorage> CaS<T> for HybridStrategy<GenLockStrategy<L>> {
// which ones upfront, so we need to implement safety measures for both.
let gen = GenLock::new(&self.fallback.0);

let previous_ptr = storage.compare_and_swap(cur_ptr, new, Ordering::SeqCst);
let swapped = ptr::eq(cur_ptr, previous_ptr);
let swap_result =
storage.compare_exchange(cur_ptr, new, Ordering::SeqCst, Ordering::SeqCst);
let (previous_ptr, swapped) = match swap_result {
Ok(previous) => (previous, true),
Err(previous) => (previous, false),
};

// Drop it here, because:
// * We can't drop it before the compare_and_swap ‒ in such case, it could get recycled,
Expand Down
2 changes: 2 additions & 0 deletions src/weak.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ mod tests {

// Replace a weak pointer with a NULL one
#[test]
// Miri-bug in std, see https://github.com/rust-lang/rust/issues/80365
#[cfg_attr(miri, ignore)]
fn reset() {
let data = Arc::new("Hello");
let shared = ArcSwapWeak::new(Arc::downgrade(&data));
Expand Down
8 changes: 6 additions & 2 deletions tests/random.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ impl OpsInstruction {
proptest! {}

const LIMIT: usize = 5;
#[cfg(not(miri))]
const SIZE: usize = 100;
#[cfg(miri)]
const SIZE: usize = 10;
static ARCS: Lazy<Vec<Arc<usize>>> = Lazy::new(|| (0..LIMIT).map(Arc::new).collect());

#[derive(Copy, Clone, Debug)]
Expand All @@ -52,7 +56,7 @@ macro_rules! t {
t!(@compose => $name, $strategy,
#[test]
fn selection(
instructions in proptest::collection::vec(SelInstruction::random(), 1..100),
instructions in proptest::collection::vec(SelInstruction::random(), 1..SIZE),
) {
let mut bare = Arc::clone(&ARCS[0]);
let a = ArcSwapAny::<_, $strategy>::from(Arc::clone(&ARCS[0]));
Expand Down Expand Up @@ -88,7 +92,7 @@ macro_rules! t {

#[test]
fn ops(
instructions in proptest::collection::vec(OpsInstruction::random(), 1..100),
instructions in proptest::collection::vec(OpsInstruction::random(), 1..SIZE),
) {
use crate::OpsInstruction::*;
let mut m = 0;
Expand Down
25 changes: 22 additions & 3 deletions tests/stress.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@ where
{
let _lock = lock();
let head = ArcSwapAny::<_, S>::from(None::<Arc<LLNode<S>>>);
#[cfg(not(miri))]
let cpus = num_cpus::get();
#[cfg(miri)]
let cpus = 2;
let barr = Barrier::new(PanicMode::Poison);
thread::scope(|scope| {
for thread in 0..cpus {
Expand Down Expand Up @@ -139,7 +142,10 @@ where
{
let _lock = lock();

#[cfg(not(miri))]
let cpus = num_cpus::get();
#[cfg(miri)]
let cpus = 2;
let barr = Barrier::new(PanicMode::Poison);
let global_cnt = AtomicUsize::new(0);
// We plan to create this many nodes during the whole test.
Expand Down Expand Up @@ -201,7 +207,10 @@ where
S: Default + Strategy<Arc<usize>> + Send + Sync,
{
let _lock = lock();
#[cfg(not(miri))]
let cpus = num_cpus::get();
#[cfg(miri)]
let cpus = 2;
let shared = ArcSwapAny::<_, S>::from(Arc::new(0));
thread::scope(|scope| {
scope.spawn(|_| {
Expand All @@ -225,14 +234,24 @@ where
assert_eq!(2, Arc::strong_count(&v));
}

#[cfg(not(miri))]
const ITER_SMALL: usize = 100;
#[cfg(not(miri))]
const ITER_MID: usize = 1000;

#[cfg(miri)]
const ITER_SMALL: usize = 2;
#[cfg(miri)]
const ITER_MID: usize = 5;

macro_rules! t {
($name: ident, $strategy: ty) => {
mod $name {
use super::*;

#[test]
fn storm_link_list_small() {
storm_link_list::<$strategy>(100, 5);
storm_link_list::<$strategy>(ITER_SMALL, 5);
}

#[test]
Expand All @@ -243,7 +262,7 @@ macro_rules! t {

#[test]
fn storm_unroll_small() {
storm_unroll::<$strategy>(100, 5);
storm_unroll::<$strategy>(ITER_SMALL, 5);
}

#[test]
Expand All @@ -254,7 +273,7 @@ macro_rules! t {

#[test]
fn load_parallel_small() {
load_parallel::<$strategy>(1000);
load_parallel::<$strategy>(ITER_MID);
}

#[test]
Expand Down

0 comments on commit a7dab6d

Please sign in to comment.