upvote
Don't most people use C++11 atomics now? You have SeqCst, Release, Acquire, and Relaxed (with Consume deprecated due to the difficulty of implementing it). You can do loads, stores, and exchanges with each ordering type. Zig, Rust, and C all use the same orderings. I guess Java has its own memory model since it's been around a lot longer, but most people have standardized around C++'s design.

Which is a slight shame since Load-Linked/Store-Conditional is pretty cool, but I guess that's limited to ARM anyways, and now they've added extensions for CAS due to speed.

reply
I've taken an interest in lock-free queues for ultra-low power embedded... think Cortex-m0, or even avr/pic.

Things get interesting when you're working with a cpu that lacks the ldrex/strem assembly instructions that makes this all work. I think youre only options at that point are disable/enable interrupts. IF anyone has any insights into this constraint I'd love to hear it.

reply
For ultra low-power embedded, wouldn't a mutex approach work just fine? You're running on a single core anyway.
reply
I'm not sure about the single-core scenario, but would love to learn if someone else wants to add something

In reality multiple threads for single core doesn't make much sense right?

reply
> In reality multiple threads for single core doesn't make much sense right?

Not necessarily, I think -- depends what you're doing.

reply
LL/SC is still hinted at in the C++11 model with std::atomic<T>::compare_exchange_weak:

https://en.cppreference.com/w/cpp/atomic/atomic/compare_exch...

reply
Really? Pretty much all atomics i’ve used have load, store of various integer sizes. I wrote a ring buffer in Go that’s very similar to the final design here using similar atomics.

https://pkg.go.dev/sync/atomic#Int64

reply
Nice one, thanks for sharing. Do you wanna share the ring buffer code itself?
reply
They generally map directly to concepts in the CPU architecture. On many architectures, load/store instructions are already guaranteed to be atomic as long as the address is properly aligned, so atomic load/store is just a load/store. Non-relaxed ordering may emit a variant load/store instruction or a separate barrier instruction. Compare-exchange will usually emit a compare and swap, or load-linked/store-conditional sequence. Things like atomic add/subtract often map to single instructions, or might be implemented as a compare-exchange in a loop.

The exact syntax and naming will of course differ, but any language that exposes low-level atomics at all is going to provide a pretty similar set of operations.

reply
yeah that’s why i was surprised by grandparent saying the atomics were c++ specific
reply
100% agree +1
reply
JVM has almost the same (C++ memory model was modeled after JVM one, with some subtle fixes).
reply
Yeah, this is quite specific to C++ (at a syntax level)
reply
Huh? Other languages that compile to machine code and offer control over struct layout and access to the machine’s atomic will work the same way.

Sure, C++ has a particular way of describing atomics in a cross-platform way, but the actual hardware operations are not specific to the language.

reply
Yeah, different languages will have different syntaxes and ways of using atomics

But at the hardware level all are kindof the same

reply