Lets suppose it is embedded development of some ARM controller. Lets suppose we have some variable, which can be assigned from an interrupt or "mainThread" - (is it a "main loop" or RTOS thread). In C world volatile keyword should be used in this case and code may look like this:
/* Some subsystem .C file */
static volatile uint8_t state;
void on_main_thread(void) {
    state = 1;     /* Changing state in this context */
}
void on_interrupt(void) {
    state = 0;     /* Changing state from interrupt */
}
uint8_t get_state(void) {
    return state;  /* Getting the state in whatever context */
}
volatile keyword is essential in this situation. Now our company rewrites some code to C++ and the same subsystem example looks like this (I use enum here to emphasize the problem)
class SomeSubsystem
{
public:
    enum class States
    {
        Off,
        Idle,
        Up,
        Down,
    };
    States getState() const { return mState; }
    void onMainThread(void) {
           mState = States::Idle;     // Changing state in this context
    }
    // Somehow this function is called from the interrupt
    void onInterrupt(void) {
           mState = States::Up;     // Changing state from interrupt
    }
private:
    States mState;   // <-- Here! Volatile? 
//...
};
Now States mState should be volatile because it is shared among different contexts. But If one sets it as volatile... Then volatile works like plague for C++ class and one have to volatilize everything around. Like volatile enum class States, getState() volatile etc. Which doesn't look good for me (am I wrong?)
So. What is the right way to handle this situation in C++?
P.S. I would try to define "this situation" as: "possible usage of a class members from different contexts like interrupts and normal code execution"
This could work if you only need a single instance of SomeSubsystem in your program (which I assume as per the c code you posted.
If you need multiple instances, then maybe you could modify mState to be a States array or some similar structure instead.
class SomeSubsystem
{
public:
    enum class States
    {
        Off,
        Idle,
        Up,
        Down,
    };
    States getState() const { return mState; }
    void onMainThread(void) {
           mState = States::Idle;     // Changing state in this context
    }
    // Somehow this function is called from the interrupt
    void onInterrupt(void) {
           mState = States::Up;     // Changing state from interrupt
    }
// Make mState public in order to access it from the rest of your code
// Otherwise, keep it private and create static set/get functions
public:
    static volatile States mState;   // <-- Here! Volatile? 
//...
};
Then define mState somewhere (eg. in SomeSubsystem.cpp)
volatile SomeSubsystem::States SomeSubsystem::mState = SomeSubsystem::States::Off;
Now you are able to access mState from anywhere in your code like this
SomeSubsystem::mState = SomeSubsystem::States::Off;
                        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