Atomic integers that panic on overflow

I wanted to check my implementation of an atomic integer that panics on overflow, so that I don't get dangerous logic errors where things that should have unique IDs do not. The following is my implementation:

static ID_FACTORY: AtomicU64 = std::sync::atomic::AtomicU64::new(0);
fn next_id() -> ConnId {
    // We fetch the value, check it isn't overflow, then swap it with another value, repeating the
    // process if it has changed in the mean time.
    loop {
        let current_val = ID_FACTORY.load(Ordering::Relaxed);
        if current_val == u64::max_value() {
            panic!("Connection id overflow");
        if ID_FACTORY.compare_and_swap(current_val, current_val + 1, Ordering::Relaxed)
            == current_val
            // Nobody changed the value since our fetch.
            break current_val + 1;

Is this the best way to implement such a type? Also, should something like this be in std?

ID_FACTORY should be a static global, not const.


Of note: if you're sequentially allocating 2^64 values at a rate of 1GHz, it'll take 584 years to get through all the values.

Not to tell you to not handle the edge case, but just to put it into perspective.


You could follow what the standard library does with Arc's MAX_REFCOUNT. That's a usize that cuts off at isize::MAX, so there's room for slop if multiple threads see the "overflow".


To be clear: isize::MAX (±1) times to observe the overflow! If you really need to be guaranteed overflow still never happen, just set it back to isize::MAX + 1 when observing overflow.