use std::sync::atomic::{AtomicU32, Ordering};
pub(crate) fn next() -> u32 {
process_id().unwrap_or_else(counter)
}
fn process_id() -> Option<u32> {
#[cfg(not(target_family = "wasm"))]
{
Some(std::process::id())
}
#[cfg(target_family = "wasm")]
{
None
}
}
fn counter() -> u32 {
static COUNTER: AtomicU32 = AtomicU32::new(0);
COUNTER.fetch_add(1, Ordering::Relaxed)
}
#[cfg(test)]
mod tests {
use super::*;
use std::collections::HashSet;
#[test]
fn the_counter_separates_concurrent_writers() {
let threads: Vec<_> = (0..8)
.map(|_| std::thread::spawn(|| (0..200).map(|_| counter()).collect::<Vec<_>>()))
.collect();
let all: Vec<u32> = threads
.into_iter()
.flat_map(|t| t.join().unwrap())
.collect();
assert_eq!(
all.iter().collect::<HashSet<_>>().len(),
all.len(),
"two writers chose the same temp suffix"
);
}
#[test]
fn next_answers_without_a_pid() {
assert_ne!(counter(), counter());
let _ = next();
}
}