У меня есть класс, представляющий конечный автомат, который должен работать в вечном цикле и проверять свое текущее состояние. В каждом состоянии машина установит свое следующее состояние и либо перейдет в состояние простоя
, либо выполнит какую-то работу. Я хотел бы разрешить другому потоку изменять состояние машины во время ее работы. Это вызовет состояние гонки, как и ожидалось. Поэтому я добавляю цикл взаимного исключения блокировки/разблокировки машины и общедоступный метод, который позволяет другим потокам изменять текущее состояние машины.
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;
};
Реализация:
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();
}
}
И метод перемещения, который позволяет другим потокам изменять текущее состояние:
void Robot::move()
{
mutal_state.lock();
previousState = currentState; // Booommm
currentState = nextState;
mutal_state.unlock();
}
Я не могу найти, что я делаю неправильно! Программа аварийно завершает работу в первой строке функции move()
. С другой стороны, GDB не работает с C++11, и трассировка кода невозможна...
ОБНОВЛЕНИЕ:
Поигравшись с кодом, я вижу, что проблема в функции перемещения. Когда программа пытается заблокировать часть кода внутри move()
, происходит сбой. Например, если перемещение выглядит так:
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();
}
Вывод:
s1
I'm waiting
I'm waiting
MOVE IS CALLED1
The program has unexpectedly finished.
Но когда перемещение
является простой функцией, ничего не делающей:
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();
}
Программа выполняется одновременно.