Boost 提供了狀態機的實現介面,採用了CRTP技術實現,下面以秒錶為例子實現一個狀態機,這是一個官方的例子,也可以參考資料:Boost Statechart 庫,狀態機的狀態轉換圖如下所示:
實現程式碼如下:
#include <stdio.h> #include <stdlib.h> #include <iostream> // std::cout #include <thread> // std::thread #include <string> #include <vector> #include <ros/ros.h> #include <boost/statechart/state_machine.hpp> #include <boost/statechart/state.hpp> #include <boost/statechart/event.hpp> #include <boost/statechart/transition.hpp> #include <boost/statechart/custom_reaction.hpp> #include <boost/range/irange.hpp> #include <boost/thread/thread.hpp> #include <ctime> using namespace std; namespace sc = boost::statechart; class EvStartStop : public sc::event<EvStartStop> { }; class EvReset : public sc::event<EvReset> { }; /*虛類,用於狀態機獲取狀態*/ class IElapsedTime { public: virtual double elapsedTime() const = 0; virtual ~IElapsedTime(){}; }; class Active; /*秒錶,狀態機*/ class StopWatch : public sc::state_machine<StopWatch, Active> { public: double elapsedTime() const { return state_cast<const IElapsedTime &>().elapsedTime(); } }; class Stopped; /*活動狀態*/ class Active : public IElapsedTime, public sc::state<Active, StopWatch, Stopped> { public: typedef sc::transition<EvReset, Active> reactions; Active(my_context ctx) : my_base(ctx), elapsed_time_(0) { cout << "Entry Active" << endl; } ~Active() { cout << "Exit Active" << endl; } double elapsedTime() const { return elapsed_time_; } double& elapsedTime() { return elapsed_time_; } private: double elapsed_time_; }; /*計時狀態*/ class Running : public IElapsedTime, public sc::state<Running, Active> { public: typedef sc::transition<EvStartStop, Stopped> reactions; Running(my_context ctx) : my_base(ctx), start_time_(std::time(0)) { cout << "Entry Running" << endl; } ~Running() { context<Active>().elapsedTime() = elapsedTime(); cout << "Exit Running" << endl; } virtual double elapsedTime() const { return context<Active>().elapsedTime() + std::difftime(std::time(0), start_time_); } private: std::time_t start_time_; }; /*停止狀態*/ class Stopped : public IElapsedTime, public sc::state<Stopped, Active> { public: typedef sc::transition<EvStartStop, Running> reactions; Stopped(my_context ctx) : my_base(ctx) { cout << "Entry Stopped" << endl; } ~Stopped() { cout << "Exit Stopped" << endl; } virtual double elapsedTime() const { return context<Active>().elapsedTime(); } }; int main(int argc, char** argv) { StopWatch myWatch; myWatch.initiate(); cout << "---" << endl; myWatch.process_event(EvStartStop()); for(int i = 0; i < 10; i++) { boost::this_thread::sleep(boost::posix_time::seconds(1)); //休眠1秒 std::cout << "time:" << myWatch.elapsedTime() << "\n"; } myWatch.process_event(EvStartStop()); boost::this_thread::sleep(boost::posix_time::seconds(1)); std::cout << "current time:" << myWatch.elapsedTime() << "\n"; cout << "---" << endl; myWatch.process_event(EvReset()); std::cout << "reset time:" << myWatch.elapsedTime() << "\n"; cout << "---" << endl; return 0; }
執行效果如下:
Entry Active Entry Stopped --- Exit Stopped Entry Running time:1 time:2 time:3 time:4 time:5 time:6 time:7 time:8 time:9 time:10 Exit Running Entry Stopped current time:10 --- Exit Stopped Exit Active Entry Active Entry Stopped reset time:0 --- Exit Stopped Exit Active