I have a class A that I overload its operator=. However it is required that I need to do something like this:
volatile A x;
A y;
x = y;
which raised an error while compiling
error: no operator "=" matches these operands
operand types are: volatile A = A
If I removed volatile, it's compilable. Is there anyway to have this compiled without removing the "volatile" (and still keep the behavior of volatile) ?
Basically this is a CUDA program in which 'x' is a shared memory ( all threads can access and modify its value ). I want it to be "volatile" in order to avoid the compiler optimization and re-use the value instead of accessing the memory address.
More on the problem: at the beginning A is just a primitive type e.g integer, volatile worked as expected and doesn't cause any problem, now I want it to be a custom class ( integer 128-bit for example ). I'm not sure why C++ complain in this case but not with primitive data type.
Thanks in advance.
Assuming the volatile
qualification is necessary, you'll have to add a volatile assignment operator to A (A& A::operator=(const A&) volatile
).
const_cast<A&>(x) = y
will make it compile, but will technically cause undefined behaviour, and will certainly remove the guarantees that volatile
gives.
The "volatile isn't a lot of use in C++ threading" comment is irrelevant to the question, which is CUDA-specific. volatile is needed for warp synchronous coding in CUDA.
volatile isn't a lot of use in C++ threading (see Dave Butenhof's explanation at http://www.lambdacs.com/cpt/FAQ.html#Q56). It's not sufficient to ensure your program flushes the data written out of core-local cache to a point where other programs can see the updates in shared memory, and given almost everyone's multi-core these days, that's a serious problem. I suggest you use proper threading synchronisation methods, such as boost's if your portability needs match it, or perhaps POSIX mutexes and condition variables, failing that more architecture dependent techniques like memory barriers or atomic operations that implicitly sync memory between cores.
I'm sure you want it to be fast, but fast and unstable isn't generally as useful as slow and reliable, especially if you ship a product that's only unstable on your customer's hardware.
Declaring a copy constructor
volatile A& operator=(volatile A&) volatile;
worked for me with nvcc. Note that you may have to pass around the non-primitive type by reference only. Else you'll need more copy-constructors that convert volatile instances to non-volatile whenever the non-primitive type is passed by value to a non-volatile parameter. It really boils down to establishing volatile-correctness (much like const-correctness).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With