使用信号处理程序触发事件时,如何让 boost.msm 正确更改状态?
How do I get boost.msm to properly change state when using a signal handler to trigger events?
我的 (boost.msm
) 状态机在使用信号处理程序时出现 'roll-back'
触发事件。但是,当我使用直接调用来触发事件时,状态
机器运行正常。
我查看了 boost 文档并在网上搜索,但似乎
所有示例都使用直接调用来触发事件。我也搜索过,
但找不到解决此主题的任何内容。
我正在学习 boost 元状态机库,看看是否
替换现有的 "home grown" 状态机库会很有用
目前由我的开发团队使用。
为了让它工作,我需要能够触发状态机事件
来自信号处理程序(处理来自 boost.signals2
的信号)。
我创建了一个简单但人为设计的示例来对其进行测试 运行 并且
当我看到第一个事件被触发后,状态时感到困惑
机器正确地(但暂时地)改变了状态(在信号处理程序中)
但显然 'rolled back' 回到 main.
当我绕过信号处理程序时(通过直接调用 process_event)
一切正常。
无可否认,测试状态机旨在执行此操作:
[state_a]--event_a-->[state_b]--event_b-->[state_c]--event_c-->{back-to-state_a}
我想知道如何使这个设计(或类似的东西)起作用
使用信号处理程序正确触发状态机事件。使用直接
电话对我来说不是一个选择,因为我只接收信号来工作。
我在下面包含了测试代码。注意主要的前半部分
函数执行信号处理程序触发和 main 的后半部分
练习直接调用触发
(使用 g++ main.cpp -omain' or 'clang++ main.cpp -omain
编译):
#include <iostream>
#include <boost/signals2.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/msm/back/state_machine.hpp>
#include <boost/msm/back/tools.hpp>
#include <boost/msm/front/state_machine_def.hpp>
#include <boost/msm/front/functor_row.hpp>
typedef boost::signals2::signal<void()> sig1_t;
//================================================================================
// ------- Sensors section
struct sensor_a {
sig1_t& get_sig() { return sig; }
void emit() { sig(); }
private:
sig1_t sig;
};
struct sensor_b {
sig1_t& get_sig() { return sig; }
void emit() { sig(); }
private:
sig1_t sig;
};
struct sensor_c {
sig1_t& get_sig() { return sig; }
void emit() { sig(); }
private:
sig1_t sig;
};
//========================================
// Sensors class
struct Sensors {
sensor_a& get_sa() {
return sa;
}
sensor_b& get_sb() {
return sb;
}
sensor_c& get_sc() {
return sc;
}
private:
sensor_a sa;
sensor_b sb;
sensor_c sc;
};
// ----- Events
struct event_a {
std::string name() const { return "event_a"; }
};
struct event_b {
std::string name() const { return "event_b"; }
};
struct event_c {
std::string name() const { return "event_c"; }
};
struct exit {
std::string name() const { return "exit"; }
};
//================================================================================
// ----- State machine section
namespace msm = boost::msm;
namespace msmf = boost::msm::front;
namespace mpl = boost::mpl;
class Controller; // forward declaration
//========================================
// testmachine class (the state machine)
struct testmachine : msmf::state_machine_def<testmachine>
{
testmachine(Controller& c) : controller(c) {}
template <class Fsm,class Event>
void no_transition(Event const& e, Fsm& ,int state) {
std::cout << "testmachine::no_transition -- No transition for event: '"
<< e.name() << "'" << " on state: " << state << std::endl;
}
//---------
struct state_a : msmf::state<> {
template <class Event,class Fsm>
void on_entry(Event const&, Fsm&) const {
std::cout << "state_a::on_entry() " << std::endl;
}
template <class Event,class Fsm>
void on_exit(Event const&, Fsm&) const {
std::cout << "state_a::on_exit()" << std::endl;
}
};
//---------
struct state_b : msmf::state<> {
template <class Event,class Fsm>
void on_entry(Event const& e, Fsm&) const {
std::cout << "state_b::on_entry() -- event: " << e.name() << std::endl;
}
template <class Event,class Fsm>
void on_exit(Event const& e, Fsm&) const {
std::cout << "state_b::on_exit() -- event: " << e.name() << std::endl;
}
};
//---------
struct state_c : msmf::state<> {
template <class Event,class Fsm>
void on_entry(Event const& e, Fsm&) const {
std::cout << "state_c::on_entry() -- event: " << e.name() << std::endl;
}
template <class Event,class Fsm>
void on_exit(Event const& e, Fsm&) const {
std::cout << "state_c::on_exit() -- event: " << e.name() << std::endl;
}
};
//---------
// Set initial state
typedef mpl::vector<state_a> initial_state;
//---------
// Transition table
struct transition_table:mpl::vector<
// Start Event Next Action Guard
msmf::Row < state_a, event_a, state_b, msmf::none, msmf::none >,
msmf::Row < state_b, event_b, state_c, msmf::none, msmf::none >,
msmf::Row < state_c, event_c, state_a, msmf::none, msmf::none >
> {};
private:
Controller& controller;
};
// state-machine back-end
typedef msm::back::state_machine<testmachine> TestMachine;
//================================================================================
// --------- controller section
namespace msm = boost::msm;
namespace mpl = boost::mpl;
// debug print helper:
std::string demangle(const std::string& mangled) {
int status;
char* c_name = abi::__cxa_demangle(mangled.c_str(), 0, 0, &status);
if(c_name){
std::string retval(c_name);
free((void*)c_name);
return retval;
}
return mangled;
}
// debug print helper (from boost msm documentation):
void pstate(TestMachine const& sm) {
typedef TestMachine::stt Stt;
typedef msm::back::generate_state_set<Stt>::type all_states;
static char const* state_names[mpl::size<all_states>::value];
mpl::for_each<all_states,boost::msm::wrap<mpl::placeholders::_1> >
(msm::back::fill_state_names<Stt>(state_names));
for (unsigned int i=0;i<TestMachine::nr_regions::value;++i){
std::cout << " -> " << demangle(state_names[sm.current_state()[i]])
<< std::endl;
}
}
//========================================
// Controller class
struct Controller {
Controller(Sensors& s) :
sensors(s),
tm(boost::ref(*this)) {
s.get_sa().get_sig().connect(boost::bind(&Controller::on_sa_event, *this));
s.get_sb().get_sig().connect(boost::bind(&Controller::on_sb_event, *this));
s.get_sc().get_sig().connect(boost::bind(&Controller::on_sc_event, *this));
tm.start();
}
void on_sa_event() {
std::cout << "Controller::on_sa_event function entered ++++++++" << std::endl;
current_state(__FUNCTION__);
trigger_event_a();
current_state(__FUNCTION__);
std::cout << "Controller::on_sa_event function exiting --------" << std::endl;
};
void on_sb_event() {
std::cout << "Controller::on_sb_event function entered ++++++++" << std::endl;
current_state(__FUNCTION__);
trigger_event_b();
current_state(__FUNCTION__);
std::cout << "Controller::on_sb_event function exiting --------" << std::endl;
};
void on_sc_event() {
std::cout << "Controller::on_sc_event function entered ++++++++" << std::endl;
current_state(__FUNCTION__);
trigger_event_c();
current_state(__FUNCTION__);
std::cout << "Controller::on_sc_event function exiting --------" << std::endl;
};
// debug print function
void current_state(const std::string& f) {
std::cout << "\nController::current_state ("
<< "called from function: " << f
<<")" << std::endl;
pstate(tm);
std::cout << std::endl;
}
void trigger_event_a() {
std::cout << "Controller::trigger_event_a" << std::endl;
tm.process_event(event_a());
current_state(__FUNCTION__);
}
void trigger_event_b() {
std::cout << "Controller::trigger_event_b" << std::endl;
tm.process_event(event_b());
current_state(__FUNCTION__);
}
void trigger_event_c() {
std::cout << "Controller::trigger_event_c" << std::endl;
tm.process_event(event_c());
current_state(__FUNCTION__);
}
private:
Sensors& sensors;
TestMachine tm;
};
//================================================================================
// --------- main
int main() {
Sensors sensors;
Controller controller(sensors);
std::cout << "Exercise state machine using signal handlers (fails):" << std::endl;
controller.current_state("***** main");
sensors.get_sa().emit();
controller.current_state("***** main");
sensors.get_sb().emit();
controller.current_state("***** main");
sensors.get_sc().emit();
controller.current_state("***** main");
std::cout << "\nExercise state machine using direct calls (works):" << std::endl;
controller.current_state("***** main");
controller.trigger_event_a();
controller.current_state("***** main");
controller.trigger_event_b();
controller.current_state("***** main");
controller.trigger_event_c();
controller.current_state("***** main");
}
这是输出:
1 state_a::on_entry()
2 Exercise state machine using signal handlers (fails):
3 Controller::current_state (called from function: ***** main)
4 -> testmachine::state_a
5 Controller::on_sa_event function entered ++++++++
6 Controller::current_state (called from function: on_sa_event)
7 -> testmachine::state_a
8 Controller::trigger_event_a
9 state_a::on_exit()
10 state_b::on_entry() -- event: event_a
11 Controller::current_state (called from function: trigger_event_a)
12 -> testmachine::state_b
13 Controller::current_state (called from function: on_sa_event)
14 -> testmachine::state_b
15 Controller::on_sa_event function exiting --------
16 Controller::current_state (called from function: ***** main)
17 -> testmachine::state_a
18 Controller::on_sb_event function entered ++++++++
19 Controller::current_state (called from function: on_sb_event)
20 -> testmachine::state_a
21 Controller::trigger_event_b
22 testmachine::no_transition -- No transition for event: 'event_b' on state: 0
23 Controller::current_state (called from function: trigger_event_b)
24 -> testmachine::state_a
25 Controller::current_state (called from function: on_sb_event)
26 -> testmachine::state_a
27 Controller::on_sb_event function exiting --------
28 Controller::current_state (called from function: ***** main)
29 -> testmachine::state_a
30 Controller::on_sc_event function entered ++++++++
31 Controller::current_state (called from function: on_sc_event)
32 -> testmachine::state_a
33 Controller::trigger_event_c
34 testmachine::no_transition -- No transition for event: 'event_c' on state: 0
35 Controller::current_state (called from function: trigger_event_c)
36 -> testmachine::state_a
37 Controller::current_state (called from function: on_sc_event)
38 -> testmachine::state_a
39 Controller::on_sc_event function exiting --------
40 Controller::current_state (called from function: ***** main)
41 -> testmachine::state_a
42 Exercise state machine using direct calls (works):
43 Controller::current_state (called from function: ***** main)
44 -> testmachine::state_a
45 Controller::trigger_event_a
46 state_a::on_exit()
47 state_b::on_entry() -- event: event_a
48 Controller::current_state (called from function: trigger_event_a)
49 -> testmachine::state_b
50 Controller::current_state (called from function: ***** main)
51 -> testmachine::state_b
52 Controller::trigger_event_b
53 state_b::on_exit() -- event: event_b
54 state_c::on_entry() -- event: event_b
55 Controller::current_state (called from function: trigger_event_b)
56 -> testmachine::state_c
57 Controller::current_state (called from function: ***** main)
58 -> testmachine::state_c
59 Controller::trigger_event_c
60 state_c::on_exit() -- event: event_c
61 state_a::on_entry()
62 Controller::current_state (called from function: trigger_event_c)
63 -> testmachine::state_a
64 Controller::current_state (called from function: ***** main)
65 -> testmachine::state_a
我通过 post 添加行号 - 处理输出文件以便于参考。
输出的第 01 行显示状态机从
初始伪状态为 state_a.
输出的第 14 行显示状态机从
在 on_sa_event 函数内部时 state_a 到 state_b。
然而,第 17 行显示状态机在测试时返回到 state_a
主要 (!)
状态机在 state_a 中保持为剩余的转换
信号处理程序测试(第 18-41 行),导致一些 'No Transition' 错误
消息。
对于直接调用练习(输出行 42-65),状态机转换
正确通过所有州并且没有区别 'current state'
从触发函数内和在 main 中时(触发后
函数调用)。
环境:
OS: "Ubuntu 16.04 LTS"
g++ 版本:(Ubuntu 5.3.1-14ubuntu2) 5.3.1 20160413
提升版本:boost_1_60_0
问题是复制*this引起的。请参见以下代码。 boost::bind 复制 *this。每个复制的 *this 都处于初始状态 (state_a)。这就是您遇到回滚的原因。
s.get_sa().get_sig().connect(boost::bind(&Controller::on_sa_event, *this));
s.get_sb().get_sig().connect(boost::bind(&Controller::on_sb_event, *this));
s.get_sc().get_sig().connect(boost::bind(&Controller::on_sc_event, *this));
如果您按如下方式复制 this 指针,您的代码将按预期工作。
s.get_sa().get_sig().connect(boost::bind(&Controller::on_sa_event, this));
s.get_sb().get_sig().connect(boost::bind(&Controller::on_sb_event, this));
s.get_sc().get_sig().connect(boost::bind(&Controller::on_sc_event, this));
你也可以绑定*this的引用,如下:
s.get_sa().get_sig().connect(boost::bind(&Controller::on_sa_event, boost::ref(*this)));
s.get_sb().get_sig().connect(boost::bind(&Controller::on_sb_event, boost::ref(*this)));
s.get_sc().get_sig().connect(boost::bind(&Controller::on_sc_event, boost::ref(*this)));
我的 (boost.msm
) 状态机在使用信号处理程序时出现 'roll-back'
触发事件。但是,当我使用直接调用来触发事件时,状态
机器运行正常。
我查看了 boost 文档并在网上搜索,但似乎 所有示例都使用直接调用来触发事件。我也搜索过, 但找不到解决此主题的任何内容。
我正在学习 boost 元状态机库,看看是否 替换现有的 "home grown" 状态机库会很有用 目前由我的开发团队使用。
为了让它工作,我需要能够触发状态机事件
来自信号处理程序(处理来自 boost.signals2
的信号)。
我创建了一个简单但人为设计的示例来对其进行测试 运行 并且 当我看到第一个事件被触发后,状态时感到困惑 机器正确地(但暂时地)改变了状态(在信号处理程序中) 但显然 'rolled back' 回到 main.
当我绕过信号处理程序时(通过直接调用 process_event) 一切正常。
无可否认,测试状态机旨在执行此操作:
[state_a]--event_a-->[state_b]--event_b-->[state_c]--event_c-->{back-to-state_a}
我想知道如何使这个设计(或类似的东西)起作用 使用信号处理程序正确触发状态机事件。使用直接 电话对我来说不是一个选择,因为我只接收信号来工作。
我在下面包含了测试代码。注意主要的前半部分
函数执行信号处理程序触发和 main 的后半部分
练习直接调用触发
(使用 g++ main.cpp -omain' or 'clang++ main.cpp -omain
编译):
#include <iostream>
#include <boost/signals2.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/msm/back/state_machine.hpp>
#include <boost/msm/back/tools.hpp>
#include <boost/msm/front/state_machine_def.hpp>
#include <boost/msm/front/functor_row.hpp>
typedef boost::signals2::signal<void()> sig1_t;
//================================================================================
// ------- Sensors section
struct sensor_a {
sig1_t& get_sig() { return sig; }
void emit() { sig(); }
private:
sig1_t sig;
};
struct sensor_b {
sig1_t& get_sig() { return sig; }
void emit() { sig(); }
private:
sig1_t sig;
};
struct sensor_c {
sig1_t& get_sig() { return sig; }
void emit() { sig(); }
private:
sig1_t sig;
};
//========================================
// Sensors class
struct Sensors {
sensor_a& get_sa() {
return sa;
}
sensor_b& get_sb() {
return sb;
}
sensor_c& get_sc() {
return sc;
}
private:
sensor_a sa;
sensor_b sb;
sensor_c sc;
};
// ----- Events
struct event_a {
std::string name() const { return "event_a"; }
};
struct event_b {
std::string name() const { return "event_b"; }
};
struct event_c {
std::string name() const { return "event_c"; }
};
struct exit {
std::string name() const { return "exit"; }
};
//================================================================================
// ----- State machine section
namespace msm = boost::msm;
namespace msmf = boost::msm::front;
namespace mpl = boost::mpl;
class Controller; // forward declaration
//========================================
// testmachine class (the state machine)
struct testmachine : msmf::state_machine_def<testmachine>
{
testmachine(Controller& c) : controller(c) {}
template <class Fsm,class Event>
void no_transition(Event const& e, Fsm& ,int state) {
std::cout << "testmachine::no_transition -- No transition for event: '"
<< e.name() << "'" << " on state: " << state << std::endl;
}
//---------
struct state_a : msmf::state<> {
template <class Event,class Fsm>
void on_entry(Event const&, Fsm&) const {
std::cout << "state_a::on_entry() " << std::endl;
}
template <class Event,class Fsm>
void on_exit(Event const&, Fsm&) const {
std::cout << "state_a::on_exit()" << std::endl;
}
};
//---------
struct state_b : msmf::state<> {
template <class Event,class Fsm>
void on_entry(Event const& e, Fsm&) const {
std::cout << "state_b::on_entry() -- event: " << e.name() << std::endl;
}
template <class Event,class Fsm>
void on_exit(Event const& e, Fsm&) const {
std::cout << "state_b::on_exit() -- event: " << e.name() << std::endl;
}
};
//---------
struct state_c : msmf::state<> {
template <class Event,class Fsm>
void on_entry(Event const& e, Fsm&) const {
std::cout << "state_c::on_entry() -- event: " << e.name() << std::endl;
}
template <class Event,class Fsm>
void on_exit(Event const& e, Fsm&) const {
std::cout << "state_c::on_exit() -- event: " << e.name() << std::endl;
}
};
//---------
// Set initial state
typedef mpl::vector<state_a> initial_state;
//---------
// Transition table
struct transition_table:mpl::vector<
// Start Event Next Action Guard
msmf::Row < state_a, event_a, state_b, msmf::none, msmf::none >,
msmf::Row < state_b, event_b, state_c, msmf::none, msmf::none >,
msmf::Row < state_c, event_c, state_a, msmf::none, msmf::none >
> {};
private:
Controller& controller;
};
// state-machine back-end
typedef msm::back::state_machine<testmachine> TestMachine;
//================================================================================
// --------- controller section
namespace msm = boost::msm;
namespace mpl = boost::mpl;
// debug print helper:
std::string demangle(const std::string& mangled) {
int status;
char* c_name = abi::__cxa_demangle(mangled.c_str(), 0, 0, &status);
if(c_name){
std::string retval(c_name);
free((void*)c_name);
return retval;
}
return mangled;
}
// debug print helper (from boost msm documentation):
void pstate(TestMachine const& sm) {
typedef TestMachine::stt Stt;
typedef msm::back::generate_state_set<Stt>::type all_states;
static char const* state_names[mpl::size<all_states>::value];
mpl::for_each<all_states,boost::msm::wrap<mpl::placeholders::_1> >
(msm::back::fill_state_names<Stt>(state_names));
for (unsigned int i=0;i<TestMachine::nr_regions::value;++i){
std::cout << " -> " << demangle(state_names[sm.current_state()[i]])
<< std::endl;
}
}
//========================================
// Controller class
struct Controller {
Controller(Sensors& s) :
sensors(s),
tm(boost::ref(*this)) {
s.get_sa().get_sig().connect(boost::bind(&Controller::on_sa_event, *this));
s.get_sb().get_sig().connect(boost::bind(&Controller::on_sb_event, *this));
s.get_sc().get_sig().connect(boost::bind(&Controller::on_sc_event, *this));
tm.start();
}
void on_sa_event() {
std::cout << "Controller::on_sa_event function entered ++++++++" << std::endl;
current_state(__FUNCTION__);
trigger_event_a();
current_state(__FUNCTION__);
std::cout << "Controller::on_sa_event function exiting --------" << std::endl;
};
void on_sb_event() {
std::cout << "Controller::on_sb_event function entered ++++++++" << std::endl;
current_state(__FUNCTION__);
trigger_event_b();
current_state(__FUNCTION__);
std::cout << "Controller::on_sb_event function exiting --------" << std::endl;
};
void on_sc_event() {
std::cout << "Controller::on_sc_event function entered ++++++++" << std::endl;
current_state(__FUNCTION__);
trigger_event_c();
current_state(__FUNCTION__);
std::cout << "Controller::on_sc_event function exiting --------" << std::endl;
};
// debug print function
void current_state(const std::string& f) {
std::cout << "\nController::current_state ("
<< "called from function: " << f
<<")" << std::endl;
pstate(tm);
std::cout << std::endl;
}
void trigger_event_a() {
std::cout << "Controller::trigger_event_a" << std::endl;
tm.process_event(event_a());
current_state(__FUNCTION__);
}
void trigger_event_b() {
std::cout << "Controller::trigger_event_b" << std::endl;
tm.process_event(event_b());
current_state(__FUNCTION__);
}
void trigger_event_c() {
std::cout << "Controller::trigger_event_c" << std::endl;
tm.process_event(event_c());
current_state(__FUNCTION__);
}
private:
Sensors& sensors;
TestMachine tm;
};
//================================================================================
// --------- main
int main() {
Sensors sensors;
Controller controller(sensors);
std::cout << "Exercise state machine using signal handlers (fails):" << std::endl;
controller.current_state("***** main");
sensors.get_sa().emit();
controller.current_state("***** main");
sensors.get_sb().emit();
controller.current_state("***** main");
sensors.get_sc().emit();
controller.current_state("***** main");
std::cout << "\nExercise state machine using direct calls (works):" << std::endl;
controller.current_state("***** main");
controller.trigger_event_a();
controller.current_state("***** main");
controller.trigger_event_b();
controller.current_state("***** main");
controller.trigger_event_c();
controller.current_state("***** main");
}
这是输出:
1 state_a::on_entry()
2 Exercise state machine using signal handlers (fails):
3 Controller::current_state (called from function: ***** main)
4 -> testmachine::state_a
5 Controller::on_sa_event function entered ++++++++
6 Controller::current_state (called from function: on_sa_event)
7 -> testmachine::state_a
8 Controller::trigger_event_a
9 state_a::on_exit()
10 state_b::on_entry() -- event: event_a
11 Controller::current_state (called from function: trigger_event_a)
12 -> testmachine::state_b
13 Controller::current_state (called from function: on_sa_event)
14 -> testmachine::state_b
15 Controller::on_sa_event function exiting --------
16 Controller::current_state (called from function: ***** main)
17 -> testmachine::state_a
18 Controller::on_sb_event function entered ++++++++
19 Controller::current_state (called from function: on_sb_event)
20 -> testmachine::state_a
21 Controller::trigger_event_b
22 testmachine::no_transition -- No transition for event: 'event_b' on state: 0
23 Controller::current_state (called from function: trigger_event_b)
24 -> testmachine::state_a
25 Controller::current_state (called from function: on_sb_event)
26 -> testmachine::state_a
27 Controller::on_sb_event function exiting --------
28 Controller::current_state (called from function: ***** main)
29 -> testmachine::state_a
30 Controller::on_sc_event function entered ++++++++
31 Controller::current_state (called from function: on_sc_event)
32 -> testmachine::state_a
33 Controller::trigger_event_c
34 testmachine::no_transition -- No transition for event: 'event_c' on state: 0
35 Controller::current_state (called from function: trigger_event_c)
36 -> testmachine::state_a
37 Controller::current_state (called from function: on_sc_event)
38 -> testmachine::state_a
39 Controller::on_sc_event function exiting --------
40 Controller::current_state (called from function: ***** main)
41 -> testmachine::state_a
42 Exercise state machine using direct calls (works):
43 Controller::current_state (called from function: ***** main)
44 -> testmachine::state_a
45 Controller::trigger_event_a
46 state_a::on_exit()
47 state_b::on_entry() -- event: event_a
48 Controller::current_state (called from function: trigger_event_a)
49 -> testmachine::state_b
50 Controller::current_state (called from function: ***** main)
51 -> testmachine::state_b
52 Controller::trigger_event_b
53 state_b::on_exit() -- event: event_b
54 state_c::on_entry() -- event: event_b
55 Controller::current_state (called from function: trigger_event_b)
56 -> testmachine::state_c
57 Controller::current_state (called from function: ***** main)
58 -> testmachine::state_c
59 Controller::trigger_event_c
60 state_c::on_exit() -- event: event_c
61 state_a::on_entry()
62 Controller::current_state (called from function: trigger_event_c)
63 -> testmachine::state_a
64 Controller::current_state (called from function: ***** main)
65 -> testmachine::state_a
我通过 post 添加行号 - 处理输出文件以便于参考。
输出的第 01 行显示状态机从 初始伪状态为 state_a.
输出的第 14 行显示状态机从 在 on_sa_event 函数内部时 state_a 到 state_b。
然而,第 17 行显示状态机在测试时返回到 state_a 主要 (!)
状态机在 state_a 中保持为剩余的转换 信号处理程序测试(第 18-41 行),导致一些 'No Transition' 错误 消息。
对于直接调用练习(输出行 42-65),状态机转换 正确通过所有州并且没有区别 'current state' 从触发函数内和在 main 中时(触发后 函数调用)。
环境: OS: "Ubuntu 16.04 LTS"
g++ 版本:(Ubuntu 5.3.1-14ubuntu2) 5.3.1 20160413
提升版本:boost_1_60_0
问题是复制*this引起的。请参见以下代码。 boost::bind 复制 *this。每个复制的 *this 都处于初始状态 (state_a)。这就是您遇到回滚的原因。
s.get_sa().get_sig().connect(boost::bind(&Controller::on_sa_event, *this));
s.get_sb().get_sig().connect(boost::bind(&Controller::on_sb_event, *this));
s.get_sc().get_sig().connect(boost::bind(&Controller::on_sc_event, *this));
如果您按如下方式复制 this 指针,您的代码将按预期工作。
s.get_sa().get_sig().connect(boost::bind(&Controller::on_sa_event, this));
s.get_sb().get_sig().connect(boost::bind(&Controller::on_sb_event, this));
s.get_sc().get_sig().connect(boost::bind(&Controller::on_sc_event, this));
你也可以绑定*this的引用,如下:
s.get_sa().get_sig().connect(boost::bind(&Controller::on_sa_event, boost::ref(*this)));
s.get_sb().get_sig().connect(boost::bind(&Controller::on_sb_event, boost::ref(*this)));
s.get_sc().get_sig().connect(boost::bind(&Controller::on_sc_event, boost::ref(*this)));