程序返回“Segmentation fault(core dumped)”。怎么了?
该实现基于示例 - '嵌套'表单文档BOOST.SML:
http://boost-experimental.github.io/sml/examples/index.html#nested
SM用于从服务器调用方法。服务器用于切换SM中的状态。
#include <boost/sml.hpp>
#include <iostream>
namespace sml = boost::sml;
using namespace std;
template <class = class Dummy>
class Server
{
struct pollEvent{};
struct msgRcdEvent{};
class States
{
public:
States(Server *server): _server(server){}
auto operator()() const noexcept
{
auto msgRcdAction = [this] {
std::cout << "HB server -> msgRcdAction " << std::endl;
_server->recvMsg();
};
auto pollAction = [this] {
std::cout << "HB server -> pollAction " << std::endl;
_server->poll();
};
using namespace sml;
return make_transition_table(
*"idle"_s + event<pollEvent> / pollAction = "Poll"_s,
"Poll"_s + event<msgRcdEvent> / msgRcdAction = "RcdMsg"_s,
"RcdMsg"_s + event<pollEvent> / pollAction = "Poll"_s
);
}
private:
Server *_server{nullptr};
};
public:
Server()
{
_states = new States(this);
_sm = new sml::sm<States>(*_states);
}
void process(){_sm->process_event(pollEvent{});}
void poll(){_sm->process_event(msgRcdEvent{});}
void recvMsg(){_sm->process_event(pollEvent{});}
private:
States *_states{nullptr};
sml::sm<States> *_sm{nullptr};
};
int main()
{
Server<> s{};
s.process();
return 0;
}
分段故障是由堆栈溢出引起的。因为_sm->process_event(...)
是递归调用的。该函数立即处理事件。
为了避免这种情况,我们需要排队事件机制而不是立即处理事件。
sml提供它。
这是代码。请参阅注释1至3。
#include <boost/sml.hpp>
#include <iostream>
#include <queue>
namespace sml = boost::sml;
using namespace std;
template <class = class Dummy>
class Server
{
struct pollEvent{};
struct msgRcdEvent{};
class States
{
public:
States(Server *server): _server(server){}
auto operator()() const noexcept
{
auto msgRcdAction =
// 2. Add parameters to lambda expression
// The second parameter is process callable object that is from
// action. The template argument `pollEvent` is the event you want
// to pass to the `process`.
// You can write multiple template arguments.
// e.g.) sml::back::process<pollEvent, msgRcdEvent>
[this] (auto const& /*ev*/, sml::back::process<pollEvent> process) {
std::cout << "HB server -> msgRcdAction " << std::endl;
_server->recvMsg(process);
};
auto pollAction =
[this] (auto const& /*ev*/, sml::back::process<msgRcdEvent> process) {
std::cout << "HB server -> pollAction " << std::endl;
_server->poll(process);
};
using namespace sml;
return make_transition_table(
*"idle"_s + event<pollEvent> / pollAction = "Poll"_s,
"Poll"_s + event<msgRcdEvent> / msgRcdAction = "RcdMsg"_s,
"RcdMsg"_s + event<pollEvent> / pollAction = "Poll"_s
);
}
private:
Server *_server{nullptr};
};
public:
Server()
{
_states = new States(this);
_sm = new sml::sm<States, sml::process_queue<std::queue>>(*_states);
}
void process1(){_sm->process_event(pollEvent{});}
// 3. Invoke process callable object
template <typename Process>
void poll(Process p){ p(msgRcdEvent{});}
template <typename Process>
void recvMsg(Process p){ p(pollEvent{});}
private:
States *_states{nullptr};
// 1. Add `sml::process_queue<std::queue>` template argument to `sml::sm`.
sml::sm<States, sml::process_queue<std::queue>> *_sm{nullptr};
};
int main()
{
Server<> s{};
s.process1();
return 0;
}
sml::back::process<pollEvent>
(注释2)是一个对事件进行排队的可调用(类似函数)对象。你可以用它来代替_sm->process_event(...)
(评论3)。队列被设置为sm
的模板参数(注释1)。