Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Jumping out of sub-machine not working correctly #400

Open
gischthefish opened this issue Oct 9, 2020 · 1 comment
Open

Jumping out of sub-machine not working correctly #400

gischthefish opened this issue Oct 9, 2020 · 1 comment

Comments

@gischthefish
Copy link

gischthefish commented Oct 9, 2020

The example of issue #283 (Jump out from substate) only works when using front::actions::process, but not with sml::back::process.
#302 (Process events to/from sub/sibling machines) should have solved the problem when exiting sub-machines.

front::actions::process doesn't help, I need to be able to choose the event getting fired.

Following the example of #283 using sml::back::process (not working):

#include <boost/sml.hpp>
#include <iostream>
#include <queue>
#include <cassert>

namespace sml = boost::sml;

struct e1 {};
struct e2 {};

auto process_e2 = [](sml::back::process<e2> processEvent) {
	std::cout << "in sub" << std::endl;
	processEvent( e2{} );
};

struct sub {
	auto operator()() {
		using namespace sml;

		return make_transition_table(
				*"start"_s + event<e1> / process_e2
		);
	}
};

struct top {
	auto operator()() {
		using namespace sml;

		return make_transition_table(
				*state<sub> + event<e2> / [] { std::cout << "jumped out from sub-state" << std::endl; } = X
		);
	}
};

int main() {
	sml::sm<top, sml::process_queue<std::queue>> sm{};
	sm.process_event(e1{});
	assert(sm.is(sml::X));
}

See the following compile error:
error.txt

Furthermore issue #121 (Submachine terminate event should be actioned in outer state) seems not to be fixed yet.
#302 (Process events to/from sub/sibling machines) should have fixed #121.
But the event that terminates the sub-machine is not being propagated to the parent sm.

The following test should work:

#include <boost/sml.hpp>
#include <cassert>
#include <iostream>

namespace sml = boost::sml;

namespace {
struct e1 {};
struct e2 {};
struct e3 {};
struct e4 {};

struct sub {
	auto operator()() const noexcept {
		using namespace sml;

		return make_transition_table(
				*"idle"_s	+ event<e3>			/ [] { std::cout << "in sub sm" << std::endl; }		= "s1"_s,
				"s1"_s		+ event<e4>			/ [] { std::cout << "finish sub sm" << std::endl; }	= X
      );
  }
};

struct composite {
	auto operator()() const noexcept {
		using namespace sml;

		return make_transition_table(
				*"idle"_s	+ event<e1>																	= "s1"_s,
				"s1"_s		+ event<e2>			/ [] { std::cout << "enter sub sm" << std::endl; }		= state<sub>,
				state<sub>	+ event<e4>			/ [] { std::cout << "exit sub sm" << std::endl; }		= X
		);
	}
};

}  // namespace

int main() {
	sml::sm<composite> sm;

	using namespace sml;
	assert(sm.is("idle"_s));
	assert(sm.is<decltype(state<sub>)>("idle"_s));

	sm.process_event(e1{});
	assert(sm.is("s1"_s));
	assert(sm.is<decltype(state<sub>)>("idle"_s));

	sm.process_event(e2{});  // enter sub sm
	assert(sm.is(state<sub>));
	assert(sm.is<decltype(state<sub>)>("idle"_s));

	sm.process_event(e3{});  // in sub sm
	assert(sm.is(state<sub>));
	assert(sm.is<decltype(state<sub>)>("s1"_s));

	sm.process_event(e4{});  // finish sub sm and propagate "exit event" to parent sm to finish parent too.
	assert(sm.is(X));
	assert(sm.is<decltype(state<sub>)>(X));
}

Propagating the event that terminated the sub-machine to the parent is a very essential feature, without that sub-machines are quite useless as the parent does not know what the sub-machine was doing, i.e. the sub-machine needs some means to tell the parent the result of the "computation".

Specifications

  • SML 1.1.3
  • GCC 9.3
@gischthefish gischthefish changed the title Jumping out of sub-machine not working corretly Jumping out of sub-machine not working correctly Oct 9, 2020
@juehallier
Copy link

juehallier commented Feb 15, 2022

I also have stumbled around this point for some hours, but indeed you can send events from the inner sm to an outer sm.
Please see a working example in the test code in the lambda function "test process_event_sent_from_substate" here.
Important fact: you'll have to add the policy sml::process_queuestd::queue when you initialize the state machine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants