Generic atomic channel that will work with custom structs as well

Viewed 30

This question is all about stdatomic.h.

Say, I want some mechanism that allows me to create atomic "channels" with any kind of data, including custom structs. I imagine something like:

struct chan {
  atomic_intptr_t ptr;
};

The idea is to have _Atomic intptr_t capable to hold reference to literally any kind of data.

Then let's image I have custom data...

struct person {
  char * name;
};

...and I publish it over my atomic channel:

struct person bob = {
    .name = "Bob"
};

struct person alice = {
    .name = "Alice"
};

struct chan c = {
    .ptr = &bob
};

Given that, the following code is one of many ways I might push new data to my channel:

atomic_exchange(&c.ptr, &alice); 

It works, yet gcc warns me:

warning: initialization of ‘atomic_intptr_t’ {aka ‘long int’} from ‘struct person *’ makes integer from pointer without a cast [-Wint-conversion]

So it feels that I've taken wrong approach.

What's the better way to have generic channel capable to exchange atomically any kind of data? Can _Generic help here?

1 Answers

Pointers can also be declared _Atomic, so I think what you want here is simply a void * which is atomic. (Maybe you're being misled by the lack of a convenience typedef for this, but it works fine, and atomic pointers are lock-free on most common platforms.) Thus:

#include <stdatomic.h>
struct chan {
    void * _Atomic ptr;
} c;

struct person {
  char * name;
} alice;

int some_integer = 8;

void add_some_stuff(void) {
    atomic_exchange(&c.ptr, &alice);
    // ...
    atomic_exchange(&c.ptr, &some_integer);
    // ...
    atomic_exchange(&c.ptr, NULL);
}

See on godbolt

Related