代码之家  ›  专栏  ›  技术社区  ›  keith

用层次状态机简化平面状态机

  •  3
  • keith  · 技术社区  · 7 年前

    我是有限状态机的新手,我正在尝试理解我是否应该使用层次化的状态机,或者坚持用最简单的方式来建模我的问题的平面结构。

    我有一个“分析器”,它可以停止,分析输入,分析输出,分析输入和输出,或清除。我有一些分析器状态在 enum 打电话 analyzer_states 以及在 analyzer_transitions .

    我可以使用一个层次化的状态机来更简单地建模吗? 或者是FSM没有帮助解决这个问题?

    #include <iostream>
    #include <cstdlib>
    #include <string>
    #include "fsm.h"
    
    enum class analyzer_transitions
    {
        start_input,
        start_output,
        clear,
        stop_input,
        stop_output,
        resume
    };
    
    enum class analyzer_states
    {
        analyzing_both,
        analyzing_input,
        analyzing_output,
        clearing_both,
        clearing_input,
        clearing_output,
        stopped,
    };
    
    inline auto output(std::string s)
    {
        return [s]()
        {
            std::cout << s << std::endl;
        };
    }
    
    int main()
    {
        fsm<analyzer_states, analyzer_transitions> machine{ analyzer_states::stopped };
    
        machine.add(
            analyzer_states::stopped, analyzer_transitions::start_input, analyzer_states::analyzing_input,
            output("-> analyzing_input"));
    
        machine.add(
            analyzer_states::stopped, analyzer_transitions::start_output, analyzer_states::analyzing_output,
            output("-> analyzing_output"));
    
        machine.add(
            analyzer_states::analyzing_input, analyzer_transitions::stop_input, analyzer_states::stopped, 
            output("-> stopped"));
    
        machine.add(
            analyzer_states::analyzing_output, analyzer_transitions::stop_output, analyzer_states::stopped, 
            output("-> stopped"));
    
        machine.add(
            analyzer_states::analyzing_both, analyzer_transitions::stop_input, analyzer_states::analyzing_output, 
            output("-> analyzing_output"));
    
        machine.add(
            analyzer_states::analyzing_both, analyzer_transitions::stop_output, analyzer_states::analyzing_input,
            output("-> analyzing_input"));
    
        machine.add(
            analyzer_states::analyzing_input, analyzer_transitions::start_output, analyzer_states::analyzing_both, 
            output("-> analyzing_both"));
    
        machine.add(
            analyzer_states::analyzing_output, analyzer_transitions::start_input, analyzer_states::analyzing_both,
            output("-> analyzing_both"));
    
        machine.add(
            analyzer_states::analyzing_input, analyzer_transitions::clear, analyzer_states::clearing_input,
            output("-> clearing_input"));
    
        machine.add(
            analyzer_states::analyzing_output, analyzer_transitions::clear, analyzer_states::clearing_output,
            output("-> clearing_output"));
    
        machine.add(
            analyzer_states::analyzing_both, analyzer_transitions::clear, analyzer_states::clearing_both,
            output("-> clearing_both"));
    
        machine.add(
            analyzer_states::clearing_input, analyzer_transitions::resume, analyzer_states::analyzing_input,
            output("-> analyzing_input"));
    
        machine.add(
            analyzer_states::clearing_output, analyzer_transitions::resume, analyzer_states::analyzing_output,
            output("-> analyzing_output"));
    
        machine.add(
            analyzer_states::clearing_both, analyzer_transitions::resume, analyzer_states::analyzing_both,
            output("-> analyzing_both"));
    
        machine.to(analyzer_transitions::start_input);
        machine.to(analyzer_transitions::start_output);
        machine.to(analyzer_transitions::stop_input);
        machine.to(analyzer_transitions::clear);
        machine.to(analyzer_transitions::resume);
    
        std::cout << "Done...";
        std::getchar();
    
        return EXIT_SUCCESS;
    }
    

    -> analyzing_input
    -> analyzing_both
    -> analyzing_output
    -> clearing_output
    -> analyzing_output
    

    fsm.h:高度

    #include <map>
    #include <functional>
    #include <atomic>
    
    template <typename State, typename Transition>
    class fsm
    {
        using handler_t = std::function<void()>;
    
        class from_t
        {
            Transition transition_;
            State state_;
    
        public:
            from_t(Transition transition, State state) :
                transition_{ transition },
                state_{ state }
            {
            }
    
            bool operator<(const from_t& other) const
            {
                if (transition_ < other.transition_)
                {
                    return true;
                }
                else if (transition_ > other.transition_)
                {
                    return false;
                }
                else
                {
                    return state_ < other.state_;
                }
            }
        };
    
        class to_t
        {
            State state_;
            handler_t handler_;
    
        public:
            to_t(State state, handler_t handler) :
                state_{ state },
                handler_{ handler }
            {
            }
    
            State state() const { return state_; }
    
            void operator()() const { handler_(); }
        };
    
        std::map<from_t, to_t> transitions_;
        std::atomic<State> state_;
    
    public:
        fsm(State initial_state) :
            state_{ initial_state }
        {
        }
    
        void add(State from, Transition transition, State to, handler_t handler)
        {
            transitions_.insert({ { transition, from }, { to, handler } });
        }
    
        void add(State from, Transition transition, State to)
        {
            add(transition, to, from, [] {});
        }
    
        bool to(Transition transition)
        {
            auto found = transitions_.find({ transition, state_ });
    
            if (found != transitions_.end())
            {
                auto& to = found->second;
    
                state_ = to.state();
    
                to();
    
                return true;
            }
            else
            {
                return false;
            }
        }
    };
    
    0 回复  |  直到 7 年前