mardi 6 novembre 2018

How to use member methods as callbacks instead of static methods for a state machine like design

I have some code that tends to act like a simple state machine. These are the objects I have:

class Actions
{
public:
    enum Action {
        action1,
        action2,
        action3
    };

    typedef void(*DoAction)(int);

    static void Start(int type) {

    }

    static void Stop(int type) {

    }

    static void NoAction(int type) {

    }
};

struct ActionCallback
{
    Actions::Action         action;
    Actions::DoAction       callback;
    ActionCallback(Actions::Action a, Actions::DoAction c) :action(a), callback(c) { }
    ActionCallback() : action(Actions::action1), callback(Actions::NoAction) { }
};

Here I have an Actions object that defines the events and callbacks and an ActionCallback objectthat contains an action and a callback.

Below is my StateMachine class - for simplicity it uses int's as states:

struct StateMachine {
    using StateMachineMap = std::map<std::pair<int, int>, ActionCallback>;
    StateMachineMap m_stateMachineMap;

    StateMachine() {
        m_stateMachineMap[std::make_pair(1, 2)] = ActionCallback(Actions::Action::action1, Actions::Start);
        m_stateMachineMap[std::make_pair(1, 3)] = ActionCallback(Actions::Action::action2, Actions::Stop);
        m_stateMachineMap[std::make_pair(1, 4)] = ActionCallback(Actions::Action::action3, Actions::Start);
        m_stateMachineMap[std::make_pair(1, 5)] = ActionCallback(Actions::Action::action3, Actions::Stop);
        m_stateMachineMap[std::make_pair(1, 6)] = ActionCallback(Actions::Action::action2, Actions::Start);
        m_stateMachineMap[std::make_pair(1, 7)] = ActionCallback(Actions::Action::action1, Actions::NoAction);
    }

    void performAction(Actions::Action action) {

    }
};

And this my main class that will contain the state machine and call performAction:

class Device {
    StateMachine stateMachine;
public:
    void TakeControl(int type) {

    }

    void ReleaseControl(int type) {

    }

    void NoAction(int type) {

    }
};

What I really want: is there a way to pass the Device methods as callbacks with this design instead of passing the static methods from Actions class ?

Something like this:

m_stateMachineMap[std::make_pair(1, 2)] = ActionCallback(Actions::Action::action1, Device::Start); // will trigger Device::Start to be called  

Right now I feel it's wrong that Device uses StateMachine and Actions which are included in StateMachine will have an instance of the Device.

Aucun commentaire:

Enregistrer un commentaire