【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 }

 

posted @ 2021-12-22 22:27  苏格拉底的落泪  阅读(361)  评论(0编辑  收藏  举报