use std::mem;
use std::sync::atomic::{AtomicU64, Ordering};
use std::thread;
static MAIN_THREAD_ID: AtomicU64 = AtomicU64::new(0);
#[inline]
fn current_thread_id() -> u64 {
unsafe { mem::transmute(thread::current().id()) }
}
pub(crate) fn assert_main_thread_or_main_unclaimed() {
let thread_id = current_thread_id();
let main_thread_id = MAIN_THREAD_ID.load(Ordering::Acquire);
if thread_id != main_thread_id && main_thread_id != 0 {
panic!("Main thread assertion failed {thread_id} != {main_thread_id}");
}
}
pub(crate) fn claim_main_thread() {
let thread_id = current_thread_id();
let old_thread_id =
MAIN_THREAD_ID.compare_exchange(0, thread_id, Ordering::AcqRel, Ordering::Acquire);
match old_thread_id {
Ok(0) => (),
Ok(_) => unreachable!(), Err(0) => {
tracing::warn!("The main thread status was already claimed by the current thread.")
}
Err(k) => panic!("The main thread status has already been claimed by thread {k}"),
}
}
pub(crate) fn release_main_thread() {
let thread_id = current_thread_id();
let old_thread_id =
MAIN_THREAD_ID.compare_exchange(thread_id, 0, Ordering::AcqRel, Ordering::Acquire);
match old_thread_id {
Ok(n) if n == thread_id => (),
Ok(_) => unreachable!(), Err(0) => tracing::warn!("The main thread status was already vacant."),
Err(k) => panic!("The main thread status has already been claimed by thread {k}"),
}
}
#[allow(unused_macros)]
macro_rules! borrow {
($val:expr) => {{
use anyhow::Context;
$val.try_borrow().with_context(|| {
format!(
"[{}:{}] {}",
std::file!(),
std::line!(),
std::stringify!($val)
)
})
}};
}
#[allow(unused_macros)]
macro_rules! borrow_mut {
($val:expr) => {{
use anyhow::Context;
$val.try_borrow_mut().with_context(|| {
format!(
"[{}:{}] {}",
std::file!(),
std::line!(),
std::stringify!($val)
)
})
}};
}
#[allow(unused_macros)]
macro_rules! with_cloned {
($($val:ident),* ; $($rest:tt)*) => {
{
$(
let $val = $val.clone();
)*
$($rest)*
}
};
}