Search code examples
c++atomicc++23seqlock

Bytewise atomic memcpy and sequence locks in C++23


I want to implement a sequence lock in C++23. If possible, it should not rely on non-standard extensions or undefined behavior.

There is the proposal P1478R8: Byte-wise atomic memcpy, which covers my exact use case. This proposal suggests to add atomic_load_per_byte_memcpy and atomic_store_per_byte_memcpy to a new header bytewise_atomic_memcpy, which can copy bytewise using atomic semantics.

How are sequence locks correctly implemented in C++ up to C++23? How to implement the functions from P1478 currently? I have not found a reference implementation of the proposal and also no other implementation of a sequence lock that handles this problem specifically. Of course, I could implement this manually, but it probably would not lead to the best performance, similar to simple implementations of memcpy. Is there a better way?

I have the feeling, that, although it's undefined behavior according to the C++ standard, in the real life, the problem is often ignored and plain memcpy gets just used.


Solution

  • How are sequence locks correctly implemented in C++ up to C++23?

    They aren't, unless all the locked variables are atomics themselves.

    How to implement the functions from P1478 currently?

    You can't.

    Sequence locks typically have data races on the payload, which are justified by ignoring the result of the data race when the sequence number was changed.

    However, in the current C++ memory model, data races are immediately undefined behavior by definition, so there is no correct way to implement a sequence lock in C++ today if the payload isn't an atomic type.

    That's the entire point of P1478, to allow it.

    I have the feeling, that, although it's undefined behavior according to the C++ standard, in the real life, the problem is often ignored and plain memcpy gets just used.

    Yes, and those implementations could break at any time.