pub mod atomic {
pub use sealed::UnsyncLoad;
#[cfg(not(all(loom, test)))]
pub use core::sync::atomic::{fence, AtomicBool, AtomicPtr};
#[cfg(all(loom, test))]
pub use loom::sync::atomic::{fence, AtomicBool, AtomicPtr};
impl<T> UnsyncLoad for AtomicPtr<T> {
type Target = T;
#[cfg(not(all(loom, test)))]
fn load_unsynced(&mut self) -> *mut Self::Target {
*self.get_mut()
}
#[cfg(all(loom, test))]
#[cfg(not(tarpaulin_include))]
fn load_unsynced(&mut self) -> *mut Self::Target {
self.with_mut(|ptr| *ptr)
}
}
mod sealed {
pub trait UnsyncLoad {
type Target;
fn load_unsynced(&mut self) -> *mut Self::Target;
}
}
}
pub mod cell {
pub use sealed::{CellNullMut, UnsafeCellWith};
#[cfg(not(all(loom, test)))]
pub use core::cell::UnsafeCell;
#[cfg(all(loom, test))]
pub use loom::cell::UnsafeCell;
#[cfg(not(all(loom, test)))]
pub use core::cell::Cell;
#[cfg(all(loom, test))]
pub use loom::cell::Cell;
impl<T: ?Sized> UnsafeCellWith for UnsafeCell<T> {
type Target = T;
#[cfg(not(all(loom, test)))]
unsafe fn with_unchecked<F, Ret>(&self, f: F) -> Ret
where
F: FnOnce(&Self::Target) -> Ret,
{
f(unsafe { &*self.get() })
}
#[cfg(all(loom, test))]
#[cfg(not(tarpaulin_include))]
unsafe fn with_unchecked<F, Ret>(&self, f: F) -> Ret
where
F: FnOnce(&Self::Target) -> Ret,
{
self.with(|ptr| f(unsafe { &*ptr }))
}
}
impl<T> CellNullMut for Cell<*mut T> {
type Target = T;
#[rustfmt::skip]
#[cfg(not(all(loom, test)))]
const NULL_MUT: Cell<*mut Self::Target> = {
Self::new(core::ptr::null_mut())
};
#[cfg(all(loom, test))]
#[cfg(not(tarpaulin_include))]
fn null_mut() -> Cell<*mut Self::Target> {
Self::new(core::ptr::null_mut())
}
}
mod sealed {
use super::Cell;
pub trait UnsafeCellWith {
type Target: ?Sized;
unsafe fn with_unchecked<F, Ret>(&self, f: F) -> Ret
where
F: FnOnce(&Self::Target) -> Ret;
}
pub trait CellNullMut {
type Target;
#[cfg(not(all(loom, test)))]
#[allow(clippy::declare_interior_mutable_const)]
const NULL_MUT: Cell<*mut Self::Target>;
#[cfg(all(loom, test))]
fn null_mut() -> Cell<*mut Self::Target>;
}
}
}
pub mod debug_abort {
#[cfg(all(test, panic = "unwind"))]
use std::panic::Location;
#[cfg(all(test, panic = "unwind"))]
#[track_caller]
pub fn on_unwind<T, F: FnOnce() -> T>(may_unwind: F) -> T {
let location = Location::caller();
let abort = DebugAbort { location };
let value = may_unwind();
core::mem::forget(abort);
value
}
#[cfg(not(all(test, panic = "unwind")))]
#[cfg(not(tarpaulin_include))]
pub fn on_unwind<T, F: FnOnce() -> T>(may_unwind: F) -> T {
may_unwind()
}
#[cfg(all(test, panic = "unwind"))]
struct DebugAbort {
location: &'static Location<'static>,
}
#[cfg(all(test, panic = "unwind"))]
#[cfg(not(tarpaulin_include))]
impl Drop for DebugAbort {
fn drop(&mut self) {
panic!("thread exits are forbidden inside {:?}, aborting", self.location);
}
}
}
pub mod hint {
#[cfg(not(all(loom, test)))]
pub use core::hint::spin_loop;
#[cfg(all(loom, test))]
pub use loom::hint::spin_loop;
}
pub mod thread {
#[cfg(all(any(feature = "yield", test), not(loom)))]
pub use std::thread::yield_now;
#[cfg(all(loom, test))]
pub use loom::thread::yield_now;
}