Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c++ access_once

Tags:

c++

c++11

I'm trying to implement the equivalent of the Linux macro ACCESS_ONCE in c++11. ACCESS_ONCE(x) takes the address of x, casts to a pointer to a volatile of the same type as x, then dereferences it. This forces the compiler to not optimize out accesses to x through this macro (and make the access occur only once here).

My attempt to do it in c++11 involves decltype:

#define ACCESS_ONCE(x) (*static_cast<decltype(x) volatile *>(&(x)))

This works for most cases but I use it once like so:

void foo(void **bar) {
  while (ACCESS_ONCE(*bar) != NULL)
    ;
}

This fails with an error:

'volatile' qualifiers cannot be applied to 'void*&'

What am I doing wrong?

like image 260
dschatz Avatar asked Dec 19 '25 09:12

dschatz


2 Answers

template<typename T>
inline T volatile &access_once(T &t) {
    return static_cast<T volatile &>(t);
}

This avoids macros, is simpler because the type deduction and reference removal is implicit in the template signature and it avoids the redundant address-of and deference operators (static casting between reference types is defined to do the same things as taking the address, casting and then dereferencing). It's just as performant and I don't think it depends on anything in C++11.

like image 77
bames53 Avatar answered Dec 21 '25 02:12

bames53


Change the macro to this:

#define ACCESS_ONCE(x) (*static_cast<std::remove_reference<decltype(x)>::type volatile *>(&(x)))

Dereferencing a pointer results in a reference. The macro is trying to cast it to a void *& volatile instead of a void * volatile like you want. You can't apply the volatile qualifier to a reference type so you have to use std::remove_reference to change it to the normal non-reference type.

like image 28
Dirk Holsopple Avatar answered Dec 21 '25 04:12

Dirk Holsopple



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!