I have a class representing a finite-state machine, which should run in a forever loop and check it's current state. In each state machine will set it's next state and either fall into idle
state or do some work. I would like to allow another thread to change state of machine while it's working. This will cause a race condition as expected. So I add a mutual exclusion lock/unlock wrapping loop of machine and the public method that allows other threads to change current state of machine.
class Robot
{
public:
enum StateType {s1,s2,s3,idle,finish};
void run();
void move();
private:
StateType currentState;
StateType nextState;
StateType previousState;
std::mutex mutal_state;
};
Implementation:
void Robot::run()
{
this->currentState = s1;
while(true)
{
mutal_state.lock();
switch(currentState)
{
case s1:
// do some useful stuff here...
currentState = idle;
nextState = s3;
break;
case s2:
// do some other useful stuff here...
currentState = idle;
nextState = finish;
break;
case s3:
// again, do some useful things...
currentState = idle;
nextState = s2;
break;
case idle:
// busy waiting...
std::cout << "I'm waiting" << std::endl;
break;
case finish:
std::cout << "Bye" << std::endl;
mutal_state.unlock();
return;
}
mutal_state.unlock();
}
}
And the move method that allows other threads to change current state:
void Robot::move()
{
mutal_state.lock();
previousState = currentState; // Booommm
currentState = nextState;
mutal_state.unlock();
}
I can't manage to find what I'm doing wrong! Program crashes in first line of the move()
function. On the other hand, the GDB is not working with C++11 and tracing code is not possible...
UPDATE:
Playing around code, I can see that problem is in move function. When the program tries to lock code piece inside move()
, crashes. For example if move is like this:
void Robot::move()
{
std::cout << "MOVE IS CALLED" << std::endl;
mutal_state.lock();
//previousState = currentState;
//std::cout << "MOVING" << std::endl;
//currentState = nextState;
mutal_state.unlock();
}
Output is:
s1
I'm waiting
I'm waiting
MOVE IS CALLED1
The program has unexpectedly finished.
But when move
is a simple function, not doing anything:
void Robot::move()
{
std::cout << "MOVE IS CALLED" << std::endl;
//mutal_state.lock();
//previousState = currentState;
//std::cout << "MOVING" << std::endl;
//currentState = nextState;
//mutal_state.unlock();
}
Program runs concurrently.