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 = ;
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_()
{
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())
{
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(), 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 = ; i < ; i++)
{
boost::this_thread::sleep(boost::posix_time::seconds()); //休眠1秒
std::cout << "time:" << myWatch.elapsedTime() << "\n";
}
myWatch.process_event(EvStartStop());
boost::this_thread::sleep(boost::posix_time::seconds());
std::cout << "current time:" << myWatch.elapsedTime() << "\n";
cout << "---" << endl;
myWatch.process_event(EvReset());
std::cout << "reset time:" << myWatch.elapsedTime() << "\n";
cout << "---" << endl;
return ;
}
运行效果如下:
Entry Active
Entry Stopped
---
Exit Stopped
Entry Running
time:
time:
time:
time:
time:
time:
time:
time:
time:
time:
Exit Running
Entry Stopped
current time:
---
Exit Stopped
Exit Active
Entry Active
Entry Stopped
reset time:
---
Exit Stopped
Exit Active