diff --git a/src/disabled/mod.rs b/src/disabled/mod.rs index fe1dd70..f2b2aa0 100644 --- a/src/disabled/mod.rs +++ b/src/disabled/mod.rs @@ -1,24 +1,3 @@ -pub(crate) mod task { - use std::future::Future; - - #[inline(always)] - pub fn task(_name: &str, f: F) -> F { - f - } -} - -pub(crate) mod operation { - use crate::ParcheckLock; - use std::future::Future; - - #[inline(always)] - pub async fn operation(_locks: Vec, f: F) -> F::Output { - f.await - } - - pub struct OperationMetadata; -} - #[macro_export] macro_rules! cfg_if { ($code:block) => {}; diff --git a/src/enabled/mod.rs b/src/enabled/mod.rs index 2e49137..53909a8 100644 --- a/src/enabled/mod.rs +++ b/src/enabled/mod.rs @@ -13,8 +13,8 @@ macro_rules! cfg_if { #[macro_export] macro_rules! task { - ($name:expr, $fut:expr) => { - $crate::task(&*$name, $fut) + ($name:expr, { $fut:expr }) => { + $crate::private::task(&*$name, $fut) }; } diff --git a/src/lib.rs b/src/lib.rs index 065368c..6315621 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,20 +1,18 @@ #[cfg(feature = "enable")] mod enabled; -#[cfg(feature = "enable")] -use enabled as api; #[cfg(not(feature = "enable"))] mod disabled; -#[cfg(not(feature = "enable"))] -use disabled as api; +#[cfg(feature = "enable")] #[doc(hidden)] pub mod private { - pub use super::api::operation::{operation, OperationMetadata}; + pub use super::enabled::{ + operation::{operation, OperationMetadata}, + task::task, + }; } -pub use api::task::task; - #[cfg(feature = "enable")] pub use enabled::runner::{runner, Runner, Trace}; diff --git a/tests/examples/basic.rs b/tests/examples/basic.rs index 36079e2..7a0fa45 100644 --- a/tests/examples/basic.rs +++ b/tests/examples/basic.rs @@ -17,25 +17,27 @@ impl Observer { } async fn execute(&self, process: &str) { - parcheck::task!(format!("execute:{process}"), async { - parcheck::operation!("append:1", { - async { - self.append(process); - } - }) - .await; - parcheck::operation!("append:2", { - async { - self.append(process); - } - }) - .await; - parcheck::operation!("append:3", { - async { - self.append(process); - } - }) - .await; + parcheck::task!(format!("execute:{process}"), { + async { + parcheck::operation!("append:1", { + async { + self.append(process); + } + }) + .await; + parcheck::operation!("append:2", { + async { + self.append(process); + } + }) + .await; + parcheck::operation!("append:3", { + async { + self.append(process); + } + }) + .await; + } }) .await; } @@ -96,7 +98,7 @@ async fn no_tasks() { async fn one_empty_task() { parcheck::runner() .run(["one"], || async move { - parcheck::task("one", async {}).await; + parcheck::task!("one", { async {} }).await; }) .await; } @@ -106,8 +108,8 @@ async fn two_empty_tasks() { parcheck::runner() .run(["task_a", "task_b"], || async move { tokio::join!( - parcheck::task("task_a", async {}), - parcheck::task("task_b", async {}), + parcheck::task!("task_a", { async {} }), + parcheck::task!("task_b", { async {} }), ); }) .await; @@ -119,8 +121,8 @@ async fn does_not_double_panic() { parcheck::runner() .run(["task_a", "task_b"], || async move { tokio::join!( - parcheck::task("task_a", async {}), - parcheck::task("task_b", async {}), + parcheck::task!("task_a", { async {} }), + parcheck::task!("task_b", { async {} }), ); panic!("some kind of test failure"); @@ -130,18 +132,20 @@ async fn does_not_double_panic() { #[tokio::test] #[should_panic( - expected = "operation 'outer' already in progress for task 'reentrant' (operation at tests/examples/basic.rs:139" + expected = "operation 'outer' already in progress for task 'reentrant' (operation at tests/examples/basic.rs:142)" )] async fn detects_reentrant_task() { parcheck::runner() .run(["reentrant"], || async move { - parcheck::task("reentrant", async { - parcheck::operation!("outer", { - async { - parcheck::operation!("inner", { async {} }).await; - } - }) - .await; + parcheck::task!("reentrant", { + async { + parcheck::operation!("outer", { + async { + parcheck::operation!("inner", { async {} }).await; + } + }) + .await; + } }) .await; }) @@ -154,9 +158,11 @@ async fn replays_prefix_trace() { // only a prefix of an actual execution .replay("0,0".parse().unwrap()) .run(["replays_prefix_trace"], || async { - parcheck::task("replays_prefix_trace", async { - for _ in 0..3 { - parcheck::operation!("op", { async {} }).await; + parcheck::task!("replays_prefix_trace", { + async { + for _ in 0..3 { + parcheck::operation!("op", { async {} }).await; + } } }) .await; @@ -169,9 +175,11 @@ async fn replays_full_trace() { parcheck::runner() .replay("0,0,0".parse().unwrap()) .run(["replays_full_trace"], || async { - parcheck::task("replays_full_trace", async { - for _ in 0..3 { - parcheck::operation!("op", { async {} }).await; + parcheck::task!("replays_full_trace", { + async { + for _ in 0..3 { + parcheck::operation!("op", { async {} }).await; + } } }) .await; diff --git a/tests/examples/disabled.rs b/tests/examples/disabled.rs index adb34df..05c6abe 100644 --- a/tests/examples/disabled.rs +++ b/tests/examples/disabled.rs @@ -2,14 +2,14 @@ use parcheck::ParcheckLock; #[tokio::test] async fn works_when_disabled() { - let result = parcheck::task!("task", async { - parcheck::operation!("op", { async { 123 } }).await + let result = parcheck::task!("task", { + async { parcheck::operation!("op", { async { 123 } }).await } }) .await; assert_eq!(result, 123); - let result = parcheck::task("task", async { - parcheck::operation!("op", { async { 123 } }).await + let result = parcheck::task!("task", { + async { parcheck::operation!("op", { async { 123 } }).await } }) .await; assert_eq!(result, 123); @@ -18,28 +18,32 @@ async fn works_when_disabled() { #[tokio::test] async fn doesnt_complain_about_unused_vars() { let x = 123; - let result = parcheck::task!(format!("task:{x}"), async { - parcheck::operation!( - "op", - vec![ParcheckLock::AcquireExclusive { - scope: "scope".into() - }], - { async { 123 } } - ) - .await + let result = parcheck::task!(format!("task:{x}"), { + async { + parcheck::operation!( + "op", + vec![ParcheckLock::AcquireExclusive { + scope: "scope".into() + }], + { async { 123 } } + ) + .await + } }) .await; assert_eq!(result, 123); - let result = parcheck::task("task", async { - parcheck::operation!( - "op", - vec![ParcheckLock::AcquireExclusive { - scope: "scope".into() - }], - { async { 123 } } - ) - .await + let result = parcheck::task!("task", { + async { + parcheck::operation!( + "op", + vec![ParcheckLock::AcquireExclusive { + scope: "scope".into() + }], + { async { 123 } } + ) + .await + } }) .await; assert_eq!(result, 123); diff --git a/tests/examples/locks.rs b/tests/examples/locks.rs index d62d71d..33a72ef 100644 --- a/tests/examples/locks.rs +++ b/tests/examples/locks.rs @@ -5,37 +5,39 @@ use parcheck::ParcheckLock; static LOCK: AtomicBool = AtomicBool::new(false); async fn execute(process: &str) { - parcheck::task(&format!("locks:{process}"), async { - parcheck::operation!( - "acquire", - vec![ParcheckLock::AcquireExclusive { scope: "".into() }], - { - async { - LOCK.compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed) - .expect("already locked, shouldn't execute this schedule"); + parcheck::task!(&format!("locks:{process}"), { + async { + parcheck::operation!( + "acquire", + vec![ParcheckLock::AcquireExclusive { scope: "".into() }], + { + async { + LOCK.compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed) + .expect("already locked, shouldn't execute this schedule"); + } } - } - ) - .await; - - parcheck::operation!("locked", { - async { - assert!(LOCK.load(Ordering::Relaxed), "should be locked"); - } - }) - .await; + ) + .await; - parcheck::operation!( - "release", - vec![ParcheckLock::Release { scope: "".into() }], - { + parcheck::operation!("locked", { async { - LOCK.compare_exchange(true, false, Ordering::Relaxed, Ordering::Relaxed) - .expect("already unlocked, shouldn't be possible"); + assert!(LOCK.load(Ordering::Relaxed), "should be locked"); } - } - ) - .await; + }) + .await; + + parcheck::operation!( + "release", + vec![ParcheckLock::Release { scope: "".into() }], + { + async { + LOCK.compare_exchange(true, false, Ordering::Relaxed, Ordering::Relaxed) + .expect("already unlocked, shouldn't be possible"); + } + } + ) + .await; + } }) .await; } @@ -56,15 +58,17 @@ async fn respects_locks() { async fn panics_if_finished_without_releasing_locks() { parcheck::runner() .run(["unreleased_locks"], || async { - parcheck::task("unreleased_locks", async { - parcheck::operation!( - "acquire", - vec![ParcheckLock::AcquireExclusive { - scope: "lock-scope".into() - }], - { async {} } - ) - .await; + parcheck::task!("unreleased_locks", { + async { + parcheck::operation!( + "acquire", + vec![ParcheckLock::AcquireExclusive { + scope: "lock-scope".into() + }], + { async {} } + ) + .await; + } }) .await; }) @@ -75,42 +79,44 @@ async fn panics_if_finished_without_releasing_locks() { #[should_panic(expected = "some tasks did not finish")] async fn detects_deadlocks() { async fn execute(name: &str, lock_a: &str, lock_b: &str) { - parcheck::task(name, async { - parcheck::operation!( - "acquire", - vec![ParcheckLock::AcquireExclusive { - scope: lock_a.into() - }], - { async {} } - ) - .await; + parcheck::task!(name, { + async { + parcheck::operation!( + "acquire", + vec![ParcheckLock::AcquireExclusive { + scope: lock_a.into() + }], + { async {} } + ) + .await; - parcheck::operation!( - "acquire", - vec![ParcheckLock::AcquireExclusive { - scope: lock_b.into() - }], - { async {} } - ) - .await; + parcheck::operation!( + "acquire", + vec![ParcheckLock::AcquireExclusive { + scope: lock_b.into() + }], + { async {} } + ) + .await; - parcheck::operation!( - "release", - vec![ParcheckLock::Release { - scope: lock_b.into() - }], - { async {} } - ) - .await; + parcheck::operation!( + "release", + vec![ParcheckLock::Release { + scope: lock_b.into() + }], + { async {} } + ) + .await; - parcheck::operation!( - "release", - vec![ParcheckLock::Release { - scope: lock_a.into() - }], - { async {} } - ) - .await; + parcheck::operation!( + "release", + vec![ParcheckLock::Release { + scope: lock_a.into() + }], + { async {} } + ) + .await; + } }) .await; }