Skip to main content

cranpose_core/
process_ids.rs

1//! Numbers that never repeat in a process, taken from any thread.
2
3#[cfg(target_has_atomic = "64")]
4use std::sync::atomic::{AtomicU64, Ordering};
5#[cfg(not(target_has_atomic = "64"))]
6use std::sync::{Mutex, PoisonError};
7
8/// Hands out numbers that never repeat in a process, from any thread: the
9/// ids of observers, listeners and other registrations.
10///
11/// A target without 64-bit atomics, such as the ESP32's Xtensa cores, takes
12/// them under a lock: portable-atomic's 64-bit atomics there keep a table of
13/// 67 locks, 4,288 bytes of RAM.
14pub struct ProcessIds {
15    #[cfg(target_has_atomic = "64")]
16    next: AtomicU64,
17    #[cfg(not(target_has_atomic = "64"))]
18    next: Mutex<u64>,
19}
20
21impl ProcessIds {
22    /// Ids from `first` on.
23    pub const fn starting_at(first: u64) -> Self {
24        Self {
25            #[cfg(target_has_atomic = "64")]
26            next: AtomicU64::new(first),
27            #[cfg(not(target_has_atomic = "64"))]
28            next: Mutex::new(first),
29        }
30    }
31
32    /// An id no earlier call returned.
33    pub fn next(&self) -> u64 {
34        #[cfg(target_has_atomic = "64")]
35        {
36            self.next.fetch_add(1, Ordering::Relaxed)
37        }
38        #[cfg(not(target_has_atomic = "64"))]
39        {
40            let mut next = self.next.lock().unwrap_or_else(PoisonError::into_inner);
41            let id = *next;
42            *next += 1;
43            id
44        }
45    }
46}