Обработка взаимного исключения в C++11

У меня есть класс, представляющий конечный автомат, который должен работать в вечном цикле и проверять свое текущее состояние. В каждом состоянии машина установит свое следующее состояние и либо перейдет в состояние простоя, либо выполнит какую-то работу. Я хотел бы разрешить другому потоку изменять состояние машины во время ее работы. Это вызовет состояние гонки, как и ожидалось. Поэтому я добавляю цикл взаимного исключения блокировки/разблокировки машины и общедоступный метод, который позволяет другим потокам изменять текущее состояние машины.

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();
}

Программа выполняется одновременно.

9
задан James McNellis 9 March 2012 в 18:09
поделиться