blob: ff49254a8bf1c904a4cee3c36869621460ded543 [file] [log] [blame]
#![allow(clippy::await_holding_lock)]
use crate::code_lock::{check_new_key, LOCKS};
#[cfg(feature = "async")]
use futures::FutureExt;
use std::panic;
#[doc(hidden)]
pub fn local_parallel_core_with_return<E>(
name: &str,
function: fn() -> Result<(), E>,
) -> Result<(), E> {
check_new_key(name);
let lock = LOCKS.get(name).unwrap();
lock.start_parallel();
let res = panic::catch_unwind(function);
lock.end_parallel();
match res {
Ok(ret) => ret,
Err(err) => {
panic::resume_unwind(err);
}
}
}
#[doc(hidden)]
pub fn local_parallel_core(name: &str, function: fn()) {
check_new_key(name);
let lock = LOCKS.get(name).unwrap();
lock.start_parallel();
let res = panic::catch_unwind(|| {
function();
});
lock.end_parallel();
if let Err(err) = res {
panic::resume_unwind(err);
}
}
#[doc(hidden)]
#[cfg(feature = "async")]
pub async fn local_async_parallel_core_with_return<E>(
name: &str,
fut: impl std::future::Future<Output = Result<(), E>> + panic::UnwindSafe,
) -> Result<(), E> {
check_new_key(name);
let lock = LOCKS.get(name).unwrap();
lock.start_parallel();
let res = fut.catch_unwind().await;
lock.end_parallel();
match res {
Ok(ret) => ret,
Err(err) => {
panic::resume_unwind(err);
}
}
}
#[doc(hidden)]
#[cfg(feature = "async")]
pub async fn local_async_parallel_core(
name: &str,
fut: impl std::future::Future<Output = ()> + panic::UnwindSafe,
) {
check_new_key(name);
let lock = LOCKS.get(name).unwrap();
lock.start_parallel();
let res = fut.catch_unwind().await;
lock.end_parallel();
if let Err(err) = res {
panic::resume_unwind(err);
}
}
#[cfg(test)]
mod tests {
#[cfg(feature = "async")]
use crate::{local_async_parallel_core, local_async_parallel_core_with_return};
use crate::{code_lock::LOCKS, local_parallel_core, local_parallel_core_with_return};
use std::{io::Error, panic};
#[test]
fn unlock_on_assert_sync_without_return() {
let _ = panic::catch_unwind(|| {
local_parallel_core("unlock_on_assert_sync_without_return", || {
assert!(false);
})
});
assert_eq!(
LOCKS
.get("unlock_on_assert_sync_without_return")
.unwrap()
.parallel_count(),
0
);
}
#[test]
fn unlock_on_assert_sync_with_return() {
let _ = panic::catch_unwind(|| {
local_parallel_core_with_return(
"unlock_on_assert_sync_with_return",
|| -> Result<(), Error> {
assert!(false);
Ok(())
},
)
});
assert_eq!(
LOCKS
.get("unlock_on_assert_sync_with_return")
.unwrap()
.parallel_count(),
0
);
}
#[tokio::test]
#[cfg(feature = "async")]
async fn unlock_on_assert_async_without_return() {
async fn demo_assert() {
assert!(false);
}
async fn call_serial_test_fn() {
local_async_parallel_core("unlock_on_assert_async_without_return", demo_assert()).await
}
// as per https://stackoverflow.com/a/66529014/320546
let _ = panic::catch_unwind(|| {
let handle = tokio::runtime::Handle::current();
let _enter_guard = handle.enter();
futures::executor::block_on(call_serial_test_fn());
});
assert_eq!(
LOCKS
.get("unlock_on_assert_async_without_return")
.unwrap()
.parallel_count(),
0
);
}
#[tokio::test]
#[cfg(feature = "async")]
async fn unlock_on_assert_async_with_return() {
async fn demo_assert() -> Result<(), Error> {
assert!(false);
Ok(())
}
#[allow(unused_must_use)]
async fn call_serial_test_fn() {
local_async_parallel_core_with_return(
"unlock_on_assert_async_with_return",
demo_assert(),
)
.await;
}
// as per https://stackoverflow.com/a/66529014/320546
let _ = panic::catch_unwind(|| {
let handle = tokio::runtime::Handle::current();
let _enter_guard = handle.enter();
futures::executor::block_on(call_serial_test_fn());
});
assert_eq!(
LOCKS
.get("unlock_on_assert_async_with_return")
.unwrap()
.parallel_count(),
0
);
}
}