#[cfg(not(feature = "single_generation"))]
use std::cell::RefCell;
#[cfg(not(all(
feature = "single_generation",
any(feature = "single_generation_mt", not(feature = "multi_thread"))
)))]
use std::cmp::Ordering;
#[cfg(not(feature = "single_generation"))]
use std::marker::PhantomData;
#[cfg(all(feature = "multi_thread", not(feature = "single_generation_mt")))]
use std::sync::atomic::AtomicUsize;
#[cfg(all(feature = "multi_thread", not(feature = "single_generation_mt")))]
use std::sync::atomic::Ordering as AtomicOrdering;
#[cfg(not(all(
feature = "single_generation",
any(feature = "single_generation_mt", not(feature = "multi_thread"))
)))]
type SeqType = usize;
#[cfg(not(feature = "single_generation"))]
thread_local! {
static TLS_SEQ: RefCell<SeqType> = const{RefCell::new(0)};
}
#[cfg(all(feature = "multi_thread", not(feature = "single_generation_mt")))]
static MT_TLS_SEQ: AtomicUsize = const { AtomicUsize::new(0) };
#[derive(Clone, Debug)]
#[cfg(not(feature = "single_generation"))]
pub(crate) struct GenerationId {
seq: SeqType,
no_send_sync: PhantomData<*mut u8>,
}
#[cfg(all(feature = "multi_thread", not(feature = "single_generation_mt")))]
#[derive(Clone, Debug)]
pub(crate) struct MTGenerationId {
seq: SeqType,
}
#[cfg(not(feature = "single_generation"))]
impl Default for GenerationId {
fn default() -> Self {
GenerationId {
seq: TLS_SEQ.with_borrow_mut(|v: &mut SeqType| {
let seq = *v;
*v = v.wrapping_add(1);
seq
}),
no_send_sync: PhantomData,
}
}
}
#[cfg(all(feature = "multi_thread", not(feature = "single_generation_mt")))]
impl Default for MTGenerationId {
fn default() -> Self {
MTGenerationId {
seq: MT_TLS_SEQ.fetch_add(1, AtomicOrdering::Relaxed),
}
}
}
#[cfg(not(feature = "single_generation"))]
impl PartialEq for GenerationId {
fn eq(&self, other: &Self) -> bool {
self.seq == other.seq
}
}
#[cfg(all(feature = "multi_thread", not(feature = "single_generation_mt")))]
impl PartialEq for MTGenerationId {
fn eq(&self, other: &Self) -> bool {
self.seq == other.seq
}
}
#[cfg(not(feature = "single_generation"))]
impl Eq for GenerationId {}
#[cfg(all(feature = "multi_thread", not(feature = "single_generation_mt")))]
impl Eq for MTGenerationId {}
#[cfg(not(feature = "single_generation"))]
impl PartialOrd for GenerationId {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
#[cfg(all(feature = "multi_thread", not(feature = "single_generation_mt")))]
impl PartialOrd for MTGenerationId {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
#[cfg(not(feature = "single_generation"))]
impl Ord for GenerationId {
fn cmp(&self, other: &Self) -> Ordering {
self.seq.cmp(&other.seq)
}
}
#[cfg(all(feature = "multi_thread", not(feature = "single_generation_mt")))]
impl Ord for MTGenerationId {
fn cmp(&self, other: &Self) -> Ordering {
self.seq.cmp(&other.seq)
}
}
#[cfg(test)]
mod tests {
#[cfg(not(feature = "single_generation"))]
use super::GenerationId;
#[cfg(all(feature = "multi_thread", not(feature = "single_generation_mt")))]
use super::MTGenerationId;
#[test]
#[cfg(not(feature = "single_generation"))]
fn dfl() {
let gid = GenerationId::default();
let next_gid = GenerationId::default();
assert_ne!(gid, next_gid);
}
#[test]
#[cfg(all(feature = "multi_thread", not(feature = "single_generation_mt")))]
fn dfl_mt() {
let gid = MTGenerationId::default();
let next_gid = MTGenerationId::default();
assert_ne!(gid, next_gid);
}
#[cfg(all(feature = "multi_thread", not(feature = "single_generation_mt")))]
fn is_sendable<T>(_: &T) -> bool
where
T: Send,
{
true
}
#[test]
#[cfg(all(feature = "multi_thread", not(feature = "single_generation_mt")))]
fn mt_sendable() {
let gid = MTGenerationId::default();
assert!(is_sendable(&gid));
}
}