Zhang
Zhang

Reputation: 3356

How do I prevent another thread to modify a state flag?

I have a class

class Device
{
    enum State {eStopped, eRunning}
    State flag = eStopped;
public:
    void run(){
        if(flag==eRunning){return;}
        /*some codes to start this device*/
        flag = eRunning;
    }
    void stop(){
        if(flag==eStopped){return;}
        /*some codes to stop this device*/
        flag = eStopped;
    }
    void doMaintenance(){
        if(flag==eRunning){return;} // We can't do maintenance when the device is running
        /*Here, the flag may be modified to eRunning in other threads*/
    }
}

In the doMaintenance() function, flag would be changed by other threads after the (flag==eRunning) check. How do I gracefully prevent this happening?

Upvotes: 0

Views: 98

Answers (1)

geza
geza

Reputation: 29970

There are other problems to solve as well. For example, suppose that the device is in a stopped state. Then, in two threads, you execute run(). Then two threads start to execute the same starting sequence. We should take care of this as well.

So, the simplest solution is to not allow any of the run(), stop() and doMaintenance() to run concurrently. This can be easily solved by a mutex:

class Device
{
    enum State {eStopped, eRunning}
    State flag = eStopped;
    std::mutex m_mutex;
public:
    void run(){
        std::scoped_lock lock(m_mutex);
        if(flag==eRunning){return;}
        /*some codes to start this device*/
        flag = eRunning;
    }
    void stop(){
        std::scoped_lock lock(m_mutex);
        if(flag==eStopped){return;}
        /*some codes to stop this device*/
        flag = eStopped;
    }
    void doMaintenance(){
        std::scoped_lock lock(m_mutex);
        if(flag==eRunning){return;} // We can't do maintenance when the device is running
        /*Here, the flag may be modified to eRunning in other threads*/
    }
}

Upvotes: 3

Related Questions