Because C++atomic
are not very "clear" to use, you can use stdatomic.h
.
https://en.cppreference.com/w/c/atomic/atomic_load
However I failed to compile example with these on gcc.
This is why I decided to use gcc builtin atomics:
https://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html
These works on both gcc
and clang
on Linux. Did not checked on MacOS yes.
Here is the code, almost similar to what I posted before. Once again excuse C style code.
In order code to be similar to what stdatomic.h
offers, I did two functions that call the builtin(s):
template<typename T>void atomic_store(T *a, T val){ return __atomic_store_n(a, val, __ATOMIC_RELAXED);}template<typename T>void atomic_store(T &a, T val){ return atomic_store(& a, val);}template<typename T>T atomic_load(T *a){ return __atomic_load_n(a, __ATOMIC_RELAXED);}template<typename T>T atomic_load(T &a){ return atomic_load(& a);}
Those suppose to be good with all integral types such int, short, char, unsigned etc.
Here is the full code in case you decide to "dig" future.
#include <cstdio>#include <sys/mman.h>#include <fcntl.h>#include <unistd.h> // sleep#include <cstdlib> // exit#include <time.h>using MyAtomicInt = int;constexpr size_t SIZE = sizeof(MyAtomicInt);constexpr const char *NAME = "nmmm";constexpr MyAtomicInt STOP = 12345;void error(const char *msg){ printf("%s\n", msg); exit(10);}template<typename T>void atomic_store(T *a, T val){ return __atomic_store_n(a, val, __ATOMIC_RELAXED);}template<typename T>void atomic_store(T &a, T val){ return atomic_store(& a, val);}template<typename T>T atomic_load(T *a){ return __atomic_load_n(a, __ATOMIC_RELAXED);}template<typename T>T atomic_load(T &a){ return atomic_load(& a);}int main(int argc, const char **argv){ int fd = shm_open(NAME, O_RDWR | O_CREAT, 0644); if (fd < 0) error("shm_open"); int t = ftruncate(fd, SIZE); if (t < 0) error("ftruncate"); void *vmem = mmap(nullptr, SIZE, PROT_WRITE, MAP_SHARED, fd, 0); if (vmem == MAP_FAILED) error("mmap"); printf("All set up! %p\n", vmem); MyAtomicInt *ai = reinterpret_cast<MyAtomicInt *>(vmem); if (argc > 1){ switch(argv[1][0]){ case 'g': case 'G': atomic_store(ai, 0); while(true){ auto x = atomic_load(ai); printf("%d\n", x); if (x == STOP) break; sleep(1); } case 's': case 'S': atomic_store(ai, STOP); break; default: { srand(time(nullptr)); MyAtomicInt const x = rand() & 0xFFFF; printf("set val to %d\n", x); atomic_store(ai, x); } break; } } munmap(vmem, SIZE);// shm_unlink(NAME);}