Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

This is in C++, other languages have different atomic primitives.


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.


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.


For ultra low-power embedded, wouldn't a mutex approach work just fine? You're running on a single core anyway.


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?


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

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


My impression was LL/SC had forward progress issues due to the difficulties of preventing false sharing of the locked memory reservation region. Updates into that region would keep invalidating the lock.

I had a version of atomic* reference counting that used LL/SC on a ppc mac mini along side x86 versions using cmpxchg16b. Code used to be sourceforge before it went to the dark side.

An early posting of the idea before I got around to implementing it. https://groups.google.com/g/comp.programming.threads/c/HZqn5...

* Std::shared_ptr and Rust ARC aren't actually atomic. You have to own a reference to do a copy. The are what POSIX calls thread-safe. With atomic reference counting, if you copy a reference, you either get a valid reference or null. Like Java references.


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...


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


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.


What's not guaranteed for "normal" loads and stores on many architectures is the order in which writes become visible to other CPU cores.


Right, that's what the various memory ordering constants are for in C++ atomics, and other languages will likely have an equivalent. On such architectures, those will emit special instructions or barriers.


100% agree +1


yeah that’s why i was surprised by grandparent saying the atomics were c++ specific


Nice one, thanks for sharing. Do you wanna share the ring buffer code itself?


JVM has almost the same (C++ memory model was modeled after JVM one, with some subtle fixes).


Yeah, this is quite specific to C++ (at a syntax level)


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.


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

But at the hardware level all are kindof the same




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: