Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/modules/ROOT/pages/version-history.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
** The deprecated APIs `process_queued_events()` and `process_single_queued_event()` are removed, use `process_event_pool(...)` instead
** The default active state switch policy is set to "after source exit" in compliance to the UML specification. The other options are not UML-compliant and will be removed (https://github.com/boostorg/msm/issues/222[#222])
** The back-end uses its own `process_result` type with new enum values instead of aliasing the enum of the `back` namespace. The old enum values are deprecated (https://github.com/boostorg/msm/issues/242[#242]) and will be removed
* fix(back, back11): Infinite recursion with event deferral in orthogonal regions (regression from 1.78) (https://github.com/boostorg/msm/issues/184[#184])

== Boost 1.91

Expand Down
2 changes: 1 addition & 1 deletion include/boost/msm/back/state_machine.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1983,7 +1983,7 @@ class state_machine : //public Derived
deferred_fct next = pair.first;
m_events_queue.m_deferred_events_queue.pop_front();
boost::msm::back::execute_return res = next();
if (res != ::boost::msm::back::HANDLED_FALSE && res != ::boost::msm::back::HANDLED_DEFERRED)
if (res != ::boost::msm::back::HANDLED_FALSE && !(res & ::boost::msm::back::HANDLED_DEFERRED))
{
not_only_deferred = true;
}
Expand Down
2 changes: 1 addition & 1 deletion include/boost/msm/back11/state_machine.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2010,7 +2010,7 @@ class state_machine : //public Derived
deferred_fct next = pair.first;
m_events_queue.m_deferred_events_queue.pop_front();
boost::msm::back::execute_return res = next();
if (res != ::boost::msm::back::HANDLED_FALSE && res != ::boost::msm::back::HANDLED_DEFERRED)
if (res != ::boost::msm::back::HANDLED_FALSE && !(res & ::boost::msm::back::HANDLED_DEFERRED))
{
not_only_deferred = true;
}
Expand Down
3 changes: 2 additions & 1 deletion test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,10 @@ add_executable(boost_msm_tests
History.cpp
KleeneDeferred.cpp
ManyDeferTransitions.cpp
OrthogonalDeferred.cpp
OrthogonalDeferred2.cpp
OrthogonalDeferred3.cpp
OrthogonalDeferred.cpp
OrthogonalDeferred4.cpp
Serialize.cpp
SerializeWithHistory.cpp
SetStates.cpp
Expand Down
1 change: 1 addition & 0 deletions test/Jamfile.v2
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ test-suite msm-unit-tests
[ run OrthogonalDeferred.cpp ]
[ run OrthogonalDeferred2.cpp ]
[ run OrthogonalDeferred3.cpp ]
[ run OrthogonalDeferred4.cpp ]
# MSVC 32-bit runs out of memory when compiling this test
[ run OrthogonalDeferredEuml.cpp : : : <toolset>msvc-14.3,<address-model>32:<build>no ]
# GCC has a bug in std::type_info::before() that leads to a segfault.
Expand Down
100 changes: 100 additions & 0 deletions test/OrthogonalDeferred4.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// Copyright 2010 Christophe Henry
// henry UNDERSCORE christophe AT hotmail DOT com
// This is an extended version of the state machine available in the boost::mpl library
// Distributed under the same license as the original.
// Copyright for the original version:
// Copyright 2005 David Abrahams and Aleksey Gurtovoy. Distributed
// under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

#ifndef BOOST_MSM_NONSTANDALONE_TEST
#define BOOST_TEST_MODULE orthogonal_deferred4_test
#endif
#include <boost/test/unit_test.hpp>

// back-end
#include "BackCommon.hpp"
//front-end
#include "FrontCommon.hpp"

namespace mpl = boost::mpl;
using namespace boost::msm::front;

namespace
{

// Events
struct Ping {};

// Actions
struct Action
{
template <typename Event, typename Fsm, typename Source, typename Target>
void operator()(const Event&, Fsm& fsm, Source&, Target&)
{
fsm.action_counter++;
}
};

// Guards
struct Conditional
{
template <typename Event, typename Fsm, typename Source, typename Target>
bool operator()(const Event&, Fsm& fsm, Source&, Target&)
{
return fsm.conditional;
}
};

struct Machine_ : test::StateMachineBase_<Machine_>
{
typedef int activate_deferred_events;

struct Deferring : state<> {};
struct Acting : state<> {};

// Two orthogonal regions
typedef mpl::vector<Deferring, Acting> initial_state;

using transition_table = mpl::vector<
// Source Event Target Action Guard
Row< Deferring, Ping, none, Defer , none>, // region 1: defer
Row< Acting , Ping, none, Action, Conditional> // region 2: handle conditionally
>;

size_t action_counter{};
bool conditional{};
};

using TestMachines = get_test_machines<Machine_>;

BOOST_AUTO_TEST_CASE_TEMPLATE(guard_reject_test, test_machine, TestMachines)
{
test_machine sm;
sm.start();

sm.process_event(Ping{});
BOOST_REQUIRE(sm.action_counter == 0);
}

BOOST_AUTO_TEST_CASE_TEMPLATE(handle_discard_test, TestMachine, TestMachines)
{
TestMachine sm;
sm.conditional = true;
sm.start();

sm.process_event(Ping{});
// Action called one times too many in old-backends
// (though behavior exists since 1.78).
size_t expected_action_counter = 2;
#ifndef BOOST_MSM_TEST_SKIP_BACKMP11
if (boost::msm::backmp11::is_backmp11_state_machine<TestMachine>::value)
{
expected_action_counter = 1;
}
#endif
BOOST_REQUIRE(sm.action_counter == expected_action_counter);
}

} // nmespace
Loading