私は有限状態マシンを表すクラスを持っています。これは永久ループで実行され、現在の状態を確認する必要があります。各状態で、マシンは次の状態を設定し、状態に陥るかidle
、何らかの作業を行います。作業中に別のスレッドがマシンの状態を変更できるようにしたいと思います。これにより、予想どおり競合状態が発生します。そこで、マシンの相互排除ロック/ロック解除ラッピング ループと、他のスレッドがマシンの現在の状態を変更できるようにするパブリック メソッドを追加します。
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();
}
}
そして、他のスレッドが現在の状態を変更できるようにする move メソッド:
void Robot::move()
{
mutal_state.lock();
previousState = currentState; // Booommm
currentState = nextState;
mutal_state.unlock();
}
私は自分が間違っていることを見つけることができません!関数の最初の行でプログラムがクラッシュしmove()
ます。一方、GDB は C++11 では動作せず、コードのトレースはできません...
アップデート:
コードをいじってみると、move 関数に問題があることがわかります。プログラムが 内のコード部分をロックしようとするとmove()
、クラッシュします。たとえば、 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.
しかし、 whenmove
は単純な関数で、何もしません:
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();
}
プログラムは同時に実行されます。