【boost::statechart】3-状态机
boost::statechart
Boost 提供了状态机的实现接口,采用了CRTP技术实现,下面以秒表为例子实现一个状态机,这是一个官方的例子,也可以参考资料:Boost Statechart 庫,状态机的状态转换图如下所示
实现代码如下:
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 #include <iostream> // std::cout 5 #include <thread> // std::thread 6 #include <string> 7 #include <vector> 8 #include <ros/ros.h> 9 #include <boost/statechart/state_machine.hpp> 10 #include <boost/statechart/state.hpp> 11 #include <boost/statechart/event.hpp> 12 #include <boost/statechart/transition.hpp> 13 #include <boost/statechart/custom_reaction.hpp> 14 #include <boost/range/irange.hpp> 15 #include <boost/thread/thread.hpp> 16 17 #include <ctime> 18 19 using namespace std; 20 namespace sc = boost::statechart; 21 22 class EvStartStop : public sc::event<EvStartStop> 23 { 24 }; 25 class EvReset : public sc::event<EvReset> 26 { 27 }; 28 29 /*虚类,用于状态机获取状态*/ 30 class IElapsedTime 31 { 32 public: 33 virtual double elapsedTime() const = 0; 34 virtual ~IElapsedTime(){}; 35 }; 36 37 class Active; 38 /*秒表,状态机*/ 39 class StopWatch : public sc::state_machine<StopWatch, Active> 40 { 41 public: 42 double elapsedTime() const 43 { 44 return state_cast<const IElapsedTime &>().elapsedTime(); 45 } 46 }; 47 48 class Stopped; 49 /*活动状态*/ 50 class Active : public IElapsedTime, public sc::state<Active, StopWatch, Stopped> 51 { 52 public: 53 typedef sc::transition<EvReset, Active> reactions; 54 55 Active(my_context ctx) 56 : my_base(ctx), 57 elapsed_time_(0) 58 { 59 cout << "Entry Active" << endl; 60 } 61 ~Active() 62 { 63 cout << "Exit Active" << endl; 64 } 65 66 double elapsedTime() const 67 { 68 return elapsed_time_; 69 } 70 double &elapsedTime() 71 { 72 return elapsed_time_; 73 } 74 75 private: 76 double elapsed_time_; 77 }; 78 79 /*计时状态*/ 80 class Running : public IElapsedTime, public sc::state<Running, Active> 81 { 82 public: 83 typedef sc::transition<EvStartStop, Stopped> reactions; 84 Running(my_context ctx) 85 : my_base(ctx), 86 start_time_(std::time(0)) 87 { 88 cout << "Entry Running" << endl; 89 } 90 ~Running() 91 { 92 context<Active>().elapsedTime() = elapsedTime(); 93 cout << "Exit Running" << endl; 94 } 95 virtual double elapsedTime() const 96 { 97 return context<Active>().elapsedTime() + std::difftime(std::time(0), start_time_); 98 } 99 100 private: 101 std::time_t start_time_; 102 }; 103 104 /*停止状态*/ 105 class Stopped : public IElapsedTime, public sc::state<Stopped, Active> 106 { 107 public: 108 typedef sc::transition<EvStartStop, Running> reactions; 109 Stopped(my_context ctx) 110 : my_base(ctx) 111 { 112 cout << "Entry Stopped" << endl; 113 } 114 ~Stopped() 115 { 116 cout << "Exit Stopped" << endl; 117 } 118 virtual double elapsedTime() const 119 { 120 return context<Active>().elapsedTime(); 121 } 122 }; 123 124 int main(int argc, char **argv) 125 { 126 StopWatch myWatch; 127 myWatch.initiate(); 128 cout << "---" << endl; 129 130 myWatch.process_event(EvStartStop()); 131 for (int i = 0; i < 10; i++) 132 { 133 boost::this_thread::sleep(boost::posix_time::seconds(1)); //休眠1秒 134 std::cout << "time:" << myWatch.elapsedTime() << "\n"; 135 } 136 myWatch.process_event(EvStartStop()); 137 boost::this_thread::sleep(boost::posix_time::seconds(1)); 138 std::cout << "current time:" << myWatch.elapsedTime() << "\n"; 139 cout << "---" << endl; 140 myWatch.process_event(EvReset()); 141 std::cout << "reset time:" << myWatch.elapsedTime() << "\n"; 142 cout << "---" << endl; 143 return 0; 144 }