Как использовать усиление MSM в сочетании с сигналом усиления?

Я действительно новичок в «boost msm», теперь у меня возник вопрос, как использовать сигнал boost в boost msm, я пробовал много раз, но не работает.

Чего я хочу добиться, так это когда машина меняет свое состояние, оператор действия отправляет сигнал, мои внешние объекты перехватывают сигнал и выполняют другие функции, но теперь я не могу отправить сигнал из машины, я не могу подключиться сигнал с внешними объектами.
Есть ли примеры?

0

Решение

Вы можете комбинировать Boost.Signals2 и Boost.MSM.

Вот простой пример сигналов2.

https://wandbox.org/permlink/XZzGIIVWXjvOPzdd (Работает демо)

#include <iostream>
#include <string>

#include <boost/signals2/signal.hpp>
#include <iostream>

// begin -- signals2 code
struct signal_data {
int i;
std::string str;
};

struct sender {
boost::signals2::signal<void(signal_data const&)> foo;

void send() {
foo(signal_data {42, "ABC"} );
}
};

struct receiver_1 {
void on_foo(signal_data const& sd) {
std::cout << __PRETTY_FUNCTION__ << " " << sd.i << ", " << sd.str << std::endl;
}
};

struct receiver_2 {
void on_foo(signal_data const& sd) {
std::cout << __PRETTY_FUNCTION__ << " " << sd.i << ", " << sd.str << std::endl;
}
};

// end -- signals2 code

int main() {
// signals setup ----------------------------------------
// external entities
receiver_1 r1;
receiver_2 r2;

sender s;

// make connection
// using lambda expression
s.foo.connect(
[&] (signal_data const& param) {
r1.on_foo(param);
}
);
// or bind
s.foo.connect(std::bind(&receiver_2::on_foo, &r2, std::placeholders::_1));
s.send();
}

Точка отправки сигнала s.send(), Если мы можем позвонить s.send() от действий МСМ цель будет достигнута.

Вот простой пример MSM.

https://wandbox.org/permlink/tnRSQ07anNe49GpO (Работает демо)

#include <iostream>
#include <string>

#include <boost/msm/back/state_machine.hpp>

#include <boost/msm/front/state_machine_def.hpp>
#include <boost/msm/front/functor_row.hpp>

// begin -- msm code
namespace msm = boost::msm;
namespace msmf = boost::msm::front;
namespace mpl = boost::mpl;

// ----- Events
struct event1 {};

// ----- State machine
struct sm1_:msmf::state_machine_def<sm1_> {
// States
struct state1:msmf::state<> {};

// Set initial state
using initial_state = state1;

// Actions
struct action {
template <class Event, class Fsm, class SourceState, class TargetState>
void operator()(Event const&, Fsm&, SourceState&, TargetState&) const {
std::cout << "action()" << std::endl;
// want to call s.send() here
}
};

// Transition table
struct transition_table:mpl::vector<
//          Start   Event   Next        Action      Guard
msmf::Row < state1, event1, msmf::none, action,     msmf::none >
> {};
};

// Pick a back-end
using sm1 = msm::back::state_machine<sm1_>;

// end -- msm code

int main() {
sm1 s1;

s1.start();
std::cout << "Send event1" << std::endl;
s1.process_event(event1());
}

Действие определяется следующим образом:

    struct action {
template <class Event, class Fsm, class SourceState, class TargetState>
void operator()(Event const&, Fsm&, SourceState&, TargetState&) const {
std::cout << "action()" << std::endl;
// want to call s.send() here
}
};

Как позвонить s.send() в действии?

Сначала добавьте ссылку на отправителя в качестве переменной-члена sm1_.

sender& s; // define sender reference as a member variable

Затем инициализируйте его в конструкторе.

sm1_(sender& s):s(s) {} // initialize sender in constructor

Затем пройдите std::ref завернутый отправитель при создании конечного автомата.

sm1 s1(std::ref(s)); // pass sender as reference

Наконец, позвоните s.send() в действии. Вы можете получить доступ s с помощью Fsm ссылка следующим образом:

struct action {
template <class Event, class Fsm, class SourceState, class TargetState>
void operator()(Event const&, Fsm& f, SourceState&, TargetState&) const {
std::cout << "action()" << std::endl;
f.s.send();
}
};

Вот весь код:

https://wandbox.org/permlink/gh83EW8eado5iOi8 (Работает демо)

#include <iostream>
#include <string>

#include <boost/signals2/signal.hpp>
#include <iostream>
#include <boost/msm/back/state_machine.hpp>

#include <boost/msm/front/state_machine_def.hpp>
#include <boost/msm/front/functor_row.hpp>

// begin -- signals2 code
struct signal_data {
int i;
std::string str;
};

struct sender {
boost::signals2::signal<void(signal_data const&)> foo;

void send() {
foo(signal_data {42, "ABC"} );
}
};

struct receiver_1 {
void on_foo(signal_data const& sd) {
std::cout << __PRETTY_FUNCTION__ << " " << sd.i << ", " << sd.str << std::endl;
}
};

struct receiver_2 {
void on_foo(signal_data const& sd) {
std::cout << __PRETTY_FUNCTION__ << " " << sd.i << ", " << sd.str << std::endl;
}
};

// end -- signals2 code

// begin -- msm code
namespace msm = boost::msm;
namespace msmf = boost::msm::front;
namespace mpl = boost::mpl;

// ----- Events
struct event1 {};

// ----- State machine
struct sm1_:msmf::state_machine_def<sm1_> {
sm1_(sender& s):s(s) {} // initialize sender in constructor

// States
struct state1:msmf::state<> {};

// Set initial state
using initial_state = state1;

// Actions
struct action {
template <class Event, class Fsm, class SourceState, class TargetState>
void operator()(Event const&, Fsm& f, SourceState&, TargetState&) const {
std::cout << "action()" << std::endl;
f.s.send();
}
};

// Transition table
struct transition_table:mpl::vector<
//          Start   Event   Next        Action      Guard
msmf::Row < state1, event1, msmf::none, action,     msmf::none >
> {};

sender& s; // define sender reference as a member variable
};

// Pick a back-end
using sm1 = msm::back::state_machine<sm1_>;

// end -- msm code

int main() {
// signals setup ----------------------------------------
// external entities
receiver_1 r1;
receiver_2 r2;

sender s;

// make connection
// using lambda expression
s.foo.connect(
[&] (signal_data const& param) {
r1.on_foo(param);
}
);
// or bind
s.foo.connect(std::bind(&receiver_2::on_foo, &r2, std::placeholders::_1));

// msm setup and process ---------------------------------
sm1 s1(std::ref(s)); // pass sender as reference

s1.start();
std::cout << "Send event1" << std::endl;
s1.process_event(event1());
}
0

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector