Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Const-correctness with volatile and external data acess

I'm an embedded C developer who has recently started messing with C++ code on an embedded device and am unsure about how const-correctness applies when a class accesses volatile data such as memory-mapped registers or data on an external device, such as an Analog-to-Digital Converter (ADC).

For example, I have classes that interface to the device's hardware modules by accessing its memory-mapped registers through a pointer, like so:

class IOPin
{
public:
    /* Constructor, destructor, other methods...*/

    // should this be a const method?
    bool ReadIOState() {return portregs_->state;}

private:
    /* Other private stuff...*/

    // Constructor points this to the right set of memory-mapped registers
    volatile struct portregs_t
    {
        uint32_t control;
        uint32_t state;
        uint32_t someotherreg;
    } *portregs_;
};

The register names are of course made up for the sake of example. I'm using a Microchip PIC32 device for anyone who's curious.

From my possibly incorrect understanding, marking a method const means that the observable state of the object should not change as far as the caller is concerned. So should the ReadIOState() method not be const because it accesses volatile data that could change at any time and thus the caller would observe the change? Or should it be const because the method isn't explicitly changing anything?

Currently, I am leaning towards not making that method const for the reason stated in the question. This is especially true after stumbling upon this GotW article, which states that the meaning of const is changing to mean "able to read concurrently". My embedded application is single-threaded, but I suppose that could be a good litmus test for constness in general.

Also, how does the compiler treat const methods? That is, what happens when I want to poll the state of the IO like this:

// wait for IO pin to go high
while(!myIOpin.ReadIOState())
{}

If ReadIOState() is const, then can the compiler reuse the value returned after one call or is it smart enough to see that it is accessing volatile data and not do that?

like image 208
Jesse DeGuire Avatar asked Jul 22 '13 14:07

Jesse DeGuire


1 Answers

You are just having pointer to the struct inside the class and you do not change the pointer, so the method can be const. The compiler should not reuse the value from the previous call, it is smart enough.

like image 84
lextiz Avatar answered Sep 20 '22 13:09

lextiz