Edit: solved, thanks Paul!

Any bored #RustLang atomics enthusiast around? I'm trying to write a kind of global unique id allocator using fetch_add and compare_exchange but now I'm not even sure if it's possible with the right orderings or if I should just do the simple thing and wrap it in a mutex ...

https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=bb48f6352ffff02df49c2e12d98655f1

#rust #atomics

Rust Playground

A browser interface to the Rust compiler to experiment with the language

I don't mind skipped IDs but duplicates are bad unless wraparound happens between them.
@algebraicterror a single “fetch_add(1, Relaxed)” should be the only atomic operation you need. That operation does wrap already, and you can detect wrapping based on the value you get.
@pauldoo Oh, right! I actually have couple of forbidden values around u16::MIN and u16::MAX but the fetch_add can just be repeated until I get a number from the allowed range. Thanks!
@algebraicterror ahh okay. :) If you have lots of forbidden values you can also do something like:
```rust
let mut result = counter.load(Relaxed);
loop {
let next = computeNextValue(result);
match counter.compare_and_exchange(result, next, Relaxed, Relaxed) {
Ok(_) => return result,
Err(actual) => result = actual
}
}
```
@pauldoo Oh, nice general solution! There's 16 bad values, I think that's acceptable performance hit in exchange for more obvious code.